- 締切済み
OpenCVで画像の一部を取り出す。
VC++でOpenCVにて画像処理をしています。 CvRect rec = cvRect(30,120,160,50); cvSetImageROI(tmp_img1, rec); これを使って画像の一部を取り出そうと思うのですが、 取り出した部分以外を白にする仕方が分かりません。 分かる方がいらっしゃいましたらよろしくお願いいたします。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- machongola
- ベストアンサー率60% (434/720)
こんばんは。補足いただきました。 (3)~(7)の間で、関数に渡すべきIPLを間違えている様です。 ・ROIを指定されたimgに対する二値化で、閾値が低かったのではないでしょうか。画像の色彩によっては真っ暗に成ったり、真っ白に成ったりします。色々な画像で試すか、閾値を半分位にセットした方が良いかもしれません。 ・ROIの領域外を白く塗り潰すのは、src_imgに対して行う事ではないでしょうか。 // (3)二値化:cvThreshold //cvThreshold (src_img_gray, img, 70, 255, CV_THRESH_BINARY); 閾値が低すぎるのでは? cvThreshold (src_img_gray, img, 128, 255, CV_THRESH_BINARY); //--------------------------------------------------------- CvRect rec = cvRect(x, y, width, height); //Thresholdのウィンドウに表示するイメージ cvSetImageROI(img, rec); //lenaのウィンドウに表示するイメージ //cvFill(img, rec, CV_RGB(255, 255, 255)); 領域外を白く塗り潰すIPLはimgでは無く、src_imgの方では? cvFill(src_img, rec, CV_RGB(255, 255, 255));//recの領域外を白で塗り潰す //------------------------------------------------------- // (7)画像を表示する
- machongola
- ベストアンサー率60% (434/720)
こんばんは。 >>取り出した部分以外を白にする仕方が分かりません。 流石に此れは正攻法では無理みたいです。 選択肢は、ROIで指定した領域の外部を矩形で白く塗り潰すか、ループしながら領域を避けてイメージデータに直描きをするか、に成りそうです。 矩形で塗り潰すやり方は、こんな感じです。参考程度に。 #define ARRAYCOUNT(a) (sizeof(a) / sizeof(a[0])) #define ARRAYEND(a) ((a) + ARRAYCOUNT(a)) static void cvFill(IplImage* img, const CvRect& cvrc, CvScalar color) { const CvRect arc[] = { {0, 0, img->width, cvrc.y},//上隅 {0, cvrc.y + cvrc.height, img->width, img->height},//下隅 {0, cvrc.y, cvrc.x, cvrc.y + cvrc.height},//左隅 {cvrc.x + cvrc.width, cvrc.y, img->width, cvrc.y + cvrc.height}//右隅 }; for(const CvRect* it = arc; it != ARRAYEND(arc); ++it) { ::cvRectangle(img, ::cvPoint(it->x, it->y), ::cvPoint(it->width, it->height), color, CV_FILLED); } } //使用する CvRect rec = cvRect(30,120,160,50); cvSetImageROI(tmp_img1, rec); cvFill(img, rec, CV_RGB(255, 255, 255));//recの領域外を白で塗り潰す
補足
早速のご回答ありがとうございます。 このことを参考にして作ってみました。 //--------------------------------------------------------------- #include <cv.h> #include <highgui.h> #include <cxcore.h> #define ARRAYCOUNT(a) (sizeof(a) / sizeof(a[0])) #define ARRAYEND(a) ((a) + ARRAYCOUNT(a)) static void cvFill(IplImage* img, const CvRect& cvrc, CvScalar color) { const CvRect arc[] = { {0, 0, img->width, cvrc.y},//上隅 {0, cvrc.y + cvrc.height, img->width, img->height},//下隅 {0, cvrc.y, cvrc.x, cvrc.y + cvrc.height},//左隅 {cvrc.x + cvrc.width, cvrc.y, img->width, cvrc.y + cvrc.height}//右隅 }; for(const CvRect* it = arc; it != ARRAYEND(arc); ++it) { ::cvRectangle(img, ::cvPoint(it->x, it->y), ::cvPoint(it->width, it->height), color, CV_FILLED); } } int main (int argc, char **argv) { int x = 30; int y = 120; int width = 160; int height = 50; IplImage *src_img = 0; IplImage *src_img_gray = 0; IplImage *tmp_img1= 0; IplImage *img =0; char imgfile[] = "chie.jpg"; src_img = cvLoadImage (imgfile, CV_LOAD_IMAGE_COLOR); img = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1); src_img_gray = cvCreateImage (cvGetSize (src_img), IPL_DEPTH_8U, 1); cvCvtColor (src_img, src_img_gray, CV_BGR2GRAY); // (2)ガウシアンフィルタで平滑化を行う cvSmooth (src_img_gray, src_img_gray, CV_GAUSSIAN, 5); // (3)二値化:cvThreshold cvThreshold (src_img_gray, img, 70, 255, CV_THRESH_BINARY); //--------------------------------------------------------- CvRect rec = cvRect(x, y, width, height); cvSetImageROI(img, rec); cvFill(img, rec, CV_RGB(255, 255, 255));//recの領域外を白で塗り潰す //------------------------------------------------------- // (7)画像を表示する cvNamedWindow ("Threshold", CV_WINDOW_AUTOSIZE); cvShowImage ("Threshold", img); cvNamedWindow ("lena", CV_WINDOW_AUTOSIZE); cvShowImage ("lena",src_img); cvWaitKey (0); //メモリを解放 cvReleaseImage (&src_img); cvReleaseImage (&src_img_gray); cvReleaseImage (&img); //ウィンドウを破棄 cvDestroyWindow ("lena"); cvDestroyWindow ("Threshold"); return 0; } //--------------------------------------------------------------- 実行してみるとROIで取り出したところが白くなった画像のみが表示されてしまいました。 よろしければ改善点を教えてください。
お礼
ご回答ありがとうございました。 無事に一部分だけを表示することができました。 またの機会がありましたらよろしくお願いいたします。