简体   繁体   English

opencv如何以高性能方式可视化非矩形区域(roi)

[英]opencv how to visualize a non-rectangular region (roi) in a performant way

I have an image (cv::Mat) and a ROI that can be seen as a mask. 我有一个图像(cv :: Mat)和一个可被视为蒙版的ROI。 I want to show the original image with the ROI blended over it. 我想显示原始图像,并在上面混合了ROI。

My mask is smaller than my origiginal image: each element represents a block in the image. 我的蒙版比我的原始图像小:每个元素代表图像中的一块。 Suppose my mask is this (note that my mask is NOT a rectangle) 假设我的面具是这个(请注意我的面具不是矩形)

0  0  1
1  1  1
0  0  0

then I would like to have the parts where (mask == 1) untouched and the rest blended with a color. 那么我想让(mask == 1)的部分保持不变,其余部分与颜色混合。 This is the code I have 这是我的代码

cv::Mat blocks = image.clone;
uint npixcol = 32;
uint npixrow = 32;
for (uint ri = 0; ri < 480; ++ri)
    for (uint ci = 0; ci < 640; ++ci)
        {
        if (mask[ri * 640 + ci])
            cv::rectangle(blocks, cv::Rect(ci * npixcol, ri * npixrow, npixcol, npixrow), cv::Scalar(0, 0, 0), CV_FILLED, 8, 0);
        }
cv::addWeighted(image, 0.5, blocks, 0.5, 0, image, -1);

How can I do this without the extra "clone" command since that is not very performant... 如果没有额外的“ clone”命令,我该怎么办呢?

to make it more clear; 使其更清楚; this is an example of what I want (the color doesn't really matter)! 这是我想要的示例(颜色并不重要)! 在此处输入图片说明

Is your mask of constant colour? 您的口罩颜色不变吗? Assuming mask is the same dimension as the image(you can easily scale it) :- 假设遮罩与图像的尺寸相同(您可以轻松缩放):

//Manually instead of addWeighted()
for (uint ri = 0; ri < 480; ++ri)
    for (uint ci = 0; ci < 640; ++ci)
        {
        if (mask[ri * 640 + ci])
        {
            image.at<uchar>(ri,ci) [0] = image.at<uchar>(ri,ci) [0] * weight_blue;
            image.at<uchar>(ri,ci) [1] = image.at<uchar>(ri,ci) [1] * weight_green;
            image.at<uchar>(ri,ci) [2] = image.at<uchar>(ri,ci) [2] * weight_red;
        }

        }    

Based on your comment, if you can make a mask with the same dimensions as the original image, you could directly modify original image pixel values using iterators. 根据您的评论,如果可以制作与原始图像尺寸相同的蒙版,则可以使用迭代器直接修改原始图像像素值。 Here is a standalone example: 这是一个独立的示例:

#include <cstdlib>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>


int
main(int argc, char *argv[])
{
  cv::Mat image = cv::imread(argv[1]);
  cv::Mat mask = cv::Mat::zeros(image.size(), CV_8U);
  // let's put some 1 in my test mask.
  cv::Mat roi = mask(cv::Rect(0,0,mask.cols/2, mask.rows/2));
  roi = 1;

  cv::Vec3b blue(255,0,0); // (B,G,R)
  float alpha = 0.5;
  // Let's have fun with iterators
  cv::MatConstIterator_<unsigned char> maskIter = mask.begin<unsigned char>();
  const cv::MatConstIterator_<unsigned char> maskIterEnd = mask.end<unsigned char>();
  cv::MatIterator_<cv::Vec3b> imageIter = image.begin<cv::Vec3b>();
  for (; maskIter != maskIterEnd; ++maskIter, ++imageIter) {
    if (*maskIter) {// mask == 1
      *imageIter = (1-alpha)*(*imageIter) + alpha*blue; // same as addWeighted 
    }
  }

  cv::namedWindow("image", 0);
  cv::imshow("image", image);
  cv::waitKey(0);
  return EXIT_SUCCESS;
}

Basically you want to have a check if your are inside the roi. 基本上,您想检查一下自己是否在roi内。 Then it should return a pointer to your original image. 然后,它应该返回一个指向原始图像的指针。 If your are not inside you want to have some kind of colour. 如果您不在室内,则希望具有某种颜色。

Your could do that with your own wrapper for Mat. 您可以使用自己的Mat包装器来做到这一点。

MyMat::at(int x, int y){
    if(inRoi(x,y)){
        return original.at(x,y);
    else
        return color(0,0,0);
}

I don't think you can point a subImage of an image onto another image. 我认为您不能将一个图像的subImage指向另一个图像。 (That means that i don't think you can redirect the pixel in your blue image onto your original image) (这意味着我认为您无法将蓝色图像中的像素重定向到原始图像上)

Mat blueImage;
Rect roi;
Mat roiInImage = blueImage(roi);
roiInImage.redirect = originalImage(roi); //don't think something like this is possible

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM