OpenCV ROI - eiichiromomma/CVMLAB GitHub Wiki
(OpenCV) ROI Region of Interest
Region Of Interest:着目領域(要するにウィンドウ)を使うと楽になる?
ROIはある領域だけ処理を施したい場合に指定する。OpenCVでは矩形のみ指定可能。
大きい画像を幾つかの領域に分けて処理をしたい時に有用
Matが標準になったのでcheatsheetより
Mat imageroi = image(Rect(10,20,100,100));
としてimageroiを弄るとimageへ変更が反映される。
処理後にIplImageのようなResetは不要。
MatにはROIの概念が無いので,Rectで絞った領域を新たなMatとして処理する。
Mat imageroi1 = image1(Rect(10,20,100,100));
Mat imageroi2 = image2(Rect(30,40,100,100));
のように2つのROIを設定し,ROIの内容をコピーしたい場合には
imageroi1.copyTo(imageroi2);
のようにROIとしたMat同士で処理する。
import cv2
import numpy as np
img = cv2.imread('lena.jpg',cv2.IMREAD_ANYCOLOR)
cv2.imshow('src',img)
# (10,50)-(20,80)の矩形をROIとする
imgROI1 = img[50:80, 10:20]
cv2.imshow('roi',imgROI1)
# ROIを0で塗り潰す
imgROI1[:,:,:] = 0
# 再表示するとROIの操作が反映されているのが分かる
cv2.imshow('src',img)
cv.GetSubRectを使う。感覚としてはC++に近い。
IplImageはROIが指定でき、随時変更、リセットができる。
cvSetImageROI(画像, 矩形情報);
画像imgに(10,10)を始点とした幅、高さが50pixelのROIを指定すると
cvSetImageROI(img, cvRect(10,10,50,50));
となる。
ちなみに
cvResetImageROI(img);
で解除。
- ROIが有効なのはOpenCVのAPIのみ
- 画像データのポインタを直接叩く場合は非適用
- cvSub等の演算を行なう場合は演算の相手に同じ大きさの画像を使うか、同じ大きさのROIを指定しなければならない
- 出力画像の大きさはROIではなく画像と同じにし、同じROIを指定する。
- 要するに元画像にROIを指定してからcvCloneImageするのが楽
画像を読んでR,G,B成分に分解し、RからGを引いた画像を表示する。但し、ROIを(10,10)-(61,61)に指定し、ポインタを直接叩いて(50,50)-(99,99)を黒く塗り潰す。
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
int main(int argc, char *argv[])
{
IplImage* srcImg = 0;
IplImage* redchannelImg = 0;
IplImage* greenchannelImg = 0;
IplImage* bluechannelImg = 0;
IplImage* outImg = 0;
if(argc<2){
printf("Usage: main <image-file-name>\n\7");
exit(0);
//画像読み込み
srcImg=cvLoadImage(argv[1],1);
if(!srcImg){
printf("Could not load image file: %s\n",argv[1]);
exit(0);
}
//チャネル画像作成
redchannelImg = cvCreateImage(cvSize(srcImg->width,srcImg->height),IPL_DEPTH_8U,1);
greenchannelImg = cvCreateImage(cvSize(srcImg->width,srcImg->height),IPL_DEPTH_8U,1);
bluechannelImg = cvCreateImage(cvSize(srcImg->width,srcImg->height),IPL_DEPTH_8U,1);
//各チャネルに分解
cvCvtPixToPlane(srcImg,bluechannelImg,greenchannelImg,redchannelImg,0);
// create a window
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin", 100, 100);
//ROI指定
cvSetImageROI(redchannelImg,cvRect(10,10,50,50));
cvSetImageROI(greenchannelImg,cvRect(10,10,50,50));
//出力先指定 cvCloneImageでROIまるごとコピー
outImg=cvCloneImage(redchannelImg);
cvSub(redchannelImg,greenchannelImg,outImg,0);
//APIを使わずにポインタから直接画像を弄ると…
for (int y=50; y<100; y++)
for (int x=50; x<100; x++)
(outImg->imageData+outImg->widthStep*y)[x] = 0;
//これをしないとROIのみ表示される
cvResetImageROI(outImg);
//画像の表示
cvShowImage("mainWin", outImg );
// wait for a key
cvWaitKey(0);
// release the image
cvReleaseImage(&srcImg );
cvReleaseImage(&redchannelImg);
cvReleaseImage(&greenchannelImg);
cvReleaseImage(&bluechannelImg);
}
こんな感じの結果になる。