如何直接在原始图像的ROI部分进行图像处理操作?

Leo*_*Leo 1 opencv image-processing

是否可以通过使用OpenCV仅在原始图像的ROI部分进行一些图像处理操作?

我在互联网上搜索一些文章.大多数代码看起来像这样:

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;
}
Run Code Online (Sandbox Code Playgroud)

实际上,它创建了一个名为roi的新图像,然后在新创建的图像中执行一些操作.我想直接在原始图像中进行操作.例如,我想做高斯模糊,只模糊原始图像中的roi部分的范围,并且不模糊该图像的其他部分.

因为新创建的图像roi与原始图像中的信息具有不同的信息.(比如坐标)我想保留这些信息.

这可能在OpenCV中这样做吗?如果是这样,怎么办?

Mik*_*iki 9

您可以使用一个Rect或两个来获取子图像Range(请参阅OpenCV doc).

Mat3b img = imread("path_to_image");
Run Code Online (Sandbox Code Playgroud)

IMG:

在此输入图像描述

Rect r(100,100,200,200);
Mat3b roi3b(img(r));
Run Code Online (Sandbox Code Playgroud)

只要您不更改图像类型,您就可以继续工作roi3b.所有更改都将反映在原始图像中img:

GaussianBlur(roi3b, roi3b, Size(), 10);
Run Code Online (Sandbox Code Playgroud)

模糊后的img:

在此输入图像描述

如果更改类型(例如从更改CV_8UC3CV_8UC1),则需要处理深层复制,因为Mat不能使用混合类型.

Mat1b roiGray;
cvtColor(roi3b, roiGray, COLOR_BGR2GRAY);
threshold(roiGray, roiGray, 200, 255, THRESH_BINARY);
Run Code Online (Sandbox Code Playgroud)

您始终可以在原始图像上复制结果,注意更正类型:

Mat3b roiGray3b;
cvtColor(roiGray, roiGray3b, COLOR_GRAY2BGR);
roiGray3b.copyTo(roi3b);
Run Code Online (Sandbox Code Playgroud)

img after threshold:

在此输入图像描述

完整代码供参考:

#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;
}
Run Code Online (Sandbox Code Playgroud)