1

Is that possible by using OpenCV to do some image processing operations only in ROI part of original image?

I search some articles on Internet. Most of codes look like this:

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

    cv::Mat image;

    image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);   
    cv::Rect roi( 100, 100,200, 200);

    //do some operations on roi

    cv::waitKey(0);
    return 0;
}

Actually, it created a new image called roi, and then do some operations in new created image. I want to do operations in original image directly. For example, I want to do gaussian blur, only blur the range of roi part in original image and do not blur other part of this image.

Because new created image roi has different informations with its information in original image. (like coordinates) I want to keep those information.

Is that possible to do this in OpenCV? If so, how to do it?

Leo
  • 303
  • 1
  • 4
  • 13

3 Answers3

10

You can get the sub-image using one either a Rect or two Range (see OpenCV doc).

Mat3b img = imread("path_to_image");

img:

enter image description here

Rect r(100,100,200,200);
Mat3b roi3b(img(r));

As long as you don't change image type you can work on roi3b. All changes will be reflected in the original image img:

GaussianBlur(roi3b, roi3b, Size(), 10);

img after blur:

enter image description here

If you change type (e.g. from CV_8UC3 to CV_8UC1), you need to work on a deep copy, since a Mat can't have mixed types.

Mat1b roiGray;
cvtColor(roi3b, roiGray, COLOR_BGR2GRAY);
threshold(roiGray, roiGray, 200, 255, THRESH_BINARY);

You can always copy the results on the original image, taking care to correct the type:

Mat3b roiGray3b;
cvtColor(roiGray, roiGray3b, COLOR_GRAY2BGR);
roiGray3b.copyTo(roi3b);

img after threshold:

enter image description here

Full code for reference:

#include <opencv2\opencv.hpp>
using namespace cv;

int main(void)
{
    Mat3b img = imread("path_to_image");

    imshow("Original", img);
    waitKey();

    Rect r(100,100,200,200);
    Mat3b roi3b(img(r));

    GaussianBlur(roi3b, roi3b, Size(), 10);

    imshow("After Blur", img);
    waitKey();

    Mat1b roiGray;
    cvtColor(roi3b, roiGray, COLOR_BGR2GRAY);

    threshold(roiGray, roiGray, 200, 255, THRESH_BINARY);

    Mat3b roiGray3b;
    cvtColor(roiGray, roiGray3b, COLOR_GRAY2BGR);
    roiGray3b.copyTo(roi3b);

    imshow("After Threshold", img);
    waitKey();

    return 0;
}
Miki
  • 40,887
  • 13
  • 123
  • 202
1

To blur the required region follow the following steps:

cv::Rect roi(x, y, w, h);
cv::GaussianBlur(image(roi), image(roi), Size(0, 0), 4); 

Follow this link for more information http://docs.opencv.org/modules/core/doc/basic_structures.html#id6

Mat::operator()(Range rowRange, Range colRange)

Mat::operator()(const Rect& roi)

  • What if I want to further process, like Canny edge detection in ROI. After I detect the edge, the final result can not be shown on the original image. cv::Rect roi(x, y, w, h); cv::GaussianBlur(image(roi), image(roi), Size(0, 0), 4); cv::Canny(image(roi), image(roi),50, 100); imshow("image",image); – Leo Oct 09 '15 at 06:25
  • Accept the answers that has helped you. Use the above code someone as done. And follow the link to place the piece of image to the original image Follow this link for the same http://stackoverflow.com/questions/10481411/opencv-copy-an-cvmat-inside-a-roi-of-another – Dr. Mallikarjun Anandhalli Oct 09 '15 at 07:11
1

I have burred the region of interest and segmented the blurred region, you can perform image processing operation on the blurred region in an original image or you can perform on segmented region.

int main() {

    Mat image;
    image=imread("Light.jpg",1);

   // image = cv::imread(argv[1], CV_LOAD_IMAGE_COLOR);   
    Rect roi( 100, 100,200, 200);
    Mat blur;
    GaussianBlur(image(roi), blur, Size(0, 0), 4); 
    imshow("blurred region",blur);
    //do some operations on roi
    imshow("aaaa",image);
    waitKey(0);
    return 0;
}