色情報による領域抽出

Last-modified: 2012-01-23 (月) 19:59:25 (913d)

概要

カメラから得られる画像がカラー画像である場合,そのカラー情報を用いることで領域を抽出することができます.今回のサンプルでは,RGB表色系においてあらかじめ閾値を設定しておき,領域抽出を行います(一般的にHSVやL*a*b*などの他の表色系に変換した後に適用されます).

サンプル

このサンプルは指定したbmpファイルの中で,R>=200,G<=50,B<=50となる画素のみを抽出するプログラムです.

メインソース

fileextraction.cpp
#include <stdio.h>
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"

#include "mask.h"

// グローバル変数群
IplImage *img=0, *mask=0, *dst=0;

int main( int argc, char** argv ){

    // 画像ファイル読み込み
    char* filename = argc == 2 ? argv[1] : (char*)"fish.bmp";
    if( (img = cvLoadImage( filename, 1)) == 0 )
        return -1;

    mask = cvCreateImage( cvSize(img->width,img->height),IPL_DEPTH_8U, 3);
    dst = cvCreateImage( cvSize(img->width,img->height),IPL_DEPTH_8U, 3);

    GetMaskRGB(img,mask,1,1);
    cvAnd( img, mask, dst );

    // 画像表示窓の準備
    cvNamedWindow("Source", 1);
    cvNamedWindow("Mask", 1);
    cvNamedWindow("Result", 1);

    // 画像表示
    cvShowImage("Source", img);
    cvShowImage("Mask", mask);
    cvShowImage("Result", dst);

    // 何かキーを押すと終了
    cvWaitKey(0);

    // 解放
    cvReleaseImage(&img);
    cvReleaseImage(&mask);
    cvReleaseImage(&dst);
    cvDestroyWindow("Source");
    cvDestroyWindow("Mask");
    cvDestroyWindow("Result");

    return 0;
}


ヘッダファイル

filemask.h
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

//■ マスク生成関数
void GetMaskRGB(IplImage* src_RGB, IplImage *mask_BW,int erosions, int dilations);


マスク画像生成

filemask.cpp
#include <cv.h>
#include <highgui.h>
#include <cxcore.h>
#include <stdio.h>
#include "mask.h"

//■ マスク生成関数--------------------------------------------------------------------
void GetMaskRGB(IplImage* src, IplImage *mask,int erosions, int dilations){
    int x = 0, y = 0;
    uchar R, G, B;
    uchar *p_src, *p_dst;
    CvPixelPosition8u pos_src, pos_dst;

    // 操作用画像
    IplImage* tmp = cvCreateImage(cvGetSize(src), IPL_DEPTH_8U , 3);

    // バックアップ
    cvCopy(src, tmp); 

    CV_INIT_PIXEL_POS( pos_src,    (unsigned char *) tmp->imageData,
                       tmp->widthStep,cvGetSize(tmp),x, y, tmp->origin);

    CV_INIT_PIXEL_POS( pos_dst, (unsigned char *) mask->imageData,
                       mask->widthStep,cvGetSize(mask),x, y,mask->origin);

    for( y=0; y < tmp->height; y++){
        for ( x=0; x < tmp->width; x++){

            p_src = CV_MOVE_TO(pos_src, x, y, 3);
            p_dst = CV_MOVE_TO(pos_dst, x, y, 3);

            R = p_src[2];
            G = p_src[1];
            B = p_src[0];

            //■ 閾値処理
            if( R >= 200 && G <= 50 && B <= 50){
                p_dst[0] = 255;
                p_dst[1] = 255;
                p_dst[2] = 255;
            }
            else{
                p_dst[0] = 0;
                p_dst[1] = 0;
                p_dst[2] = 0;
            }

        }
    }
    
    if ( erosions > 0 )  cvErode( mask,mask, 0,erosions );
    if ( dilations > 0 ) cvDilate( mask,mask,0,dilations );

    cvReleaseImage(&tmp); 
}
//------------------------------------------------------------------------------------------------------


[注意!!]
IplImage?にはBGRの順に画素値が格納されています.
そのため,本プログラムではこのような記述をしています.

R = p_src[2];
G = p_src[1];
B = p_src[0];

出力結果

fish.png
図. 原画像


mask.pngresult.png
図. マスク画像図. 抽出結果

添付ファイル: fileresult.bmp 305件 [詳細] filemask.png 480件 [詳細] filemask.h 1011件 [詳細] filemask.cpp 1007件 [詳細] fileresult.png 411件 [詳細] filemask.bmp 288件 [詳細] filefish.png 638件 [詳細] fileextraction.cpp 1004件 [詳細] filefish.bmp 332件 [詳細]