Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ opencv如何以高效的方式可视化非矩形区域(roi)_C++_Opencv_Mask_Roi_Visualize - Fatal编程技术网

C++ opencv如何以高效的方式可视化非矩形区域(roi)

C++ opencv如何以高效的方式可视化非矩形区域(roi),c++,opencv,mask,roi,visualize,C++,Opencv,Mask,Roi,Visualize,我有一个图像(cv::Mat)和一个可以被视为遮罩的ROI。我想显示原始图像,上面混合了ROI 我的遮罩比原始图像小:每个元素代表图像中的一个块。假设我的蒙版是这样的(请注意,我的蒙版不是矩形) 然后我想让(mask==1)部分保持不变,其余部分与颜色混合。这是我的密码 cv::Mat blocks = image.clone; uint npixcol = 32; uint npixrow = 32; for (uint ri = 0; ri < 480; ++ri) for (

我有一个图像(cv::Mat)和一个可以被视为遮罩的ROI。我想显示原始图像,上面混合了ROI

我的遮罩比原始图像小:每个元素代表图像中的一个块。假设我的蒙版是这样的(请注意,我的蒙版不是矩形)

然后我想让(mask==1)部分保持不变,其余部分与颜色混合。这是我的密码

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);
cv::Mat blocks=image.clone;
uint-npixcol=32;
uint npixrow=32;
对于(uint ri=0;ri<480;++ri)
对于(uint ci=0;ci<640;++ci)
{
if(掩码[ri*640+ci])
cv::矩形(块,cv::矩形(ci*npixcol,ri*npixrow,npixcol,npixrow),cv::标量(0,0,0),cv_填充,8,0);
}
cv::addWeighted(图像,0.5,块,0.5,0,图像,-1);
如果没有额外的“克隆”命令,我怎么能做到这一点,因为这不是很好的性能


使之更清楚;这是我想要的一个例子(颜色并不重要)

基本上,您需要检查您的投资是否在投资回报率内。然后它应该返回一个指向原始图像的指针。如果你的眼睛不在里面,你希望有某种颜色

你们可以用你们自己的垫子包装纸来做

MyMat::at(int x, int y){
    if(inRoi(x,y)){
        return original.at(x,y);
    else
        return color(0,0,0);
}
我认为你不能把一个图像的子图像指向另一个图像。(这意味着我认为您无法将蓝色图像中的像素重定向到原始图像上)


根据您的评论,如果可以制作与原始图像尺寸相同的遮罩,则可以使用迭代器直接修改原始图像像素值。以下是一个独立的示例:

#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;
}
#包括
#包括
#包括
int
main(int argc,char*argv[])
{
cv::Mat image=cv::imread(argv[1]);
cv::Mat mask=cv::Mat::零(image.size(),cv_8U);
//让我们在我的测试面具上放一些1。
cv::Mat roi=掩码(cv::Rect(0,0,mask.cols/2,mask.rows/2));
投资回报率=1;
cv::Vec3b蓝(255,0,0);/(B,G,R)
浮动α=0.5;
//让我们享受迭代器带来的乐趣
cv::matconditerator_uumaskiter=mask.begin();
常数cv::matconstrutator_uumaskiterend=mask.end();
cv::MatIterator_uImageiter=image.begin();
对于(;maskIter!=maskIterEnd;++maskIter,++imageIter){
如果(*maskIter){//mask==1
*imageIter=(1-alpha)*(*imageIter)+alpha*blue;//与addWeighted相同
}
}
cv::namedWindow(“图像”,0);
cv::imshow(“图像”,图像);
cv::waitKey(0);
返回退出成功;
}

你的面具颜色不变吗?假设遮罩与图像的尺寸相同(您可以轻松缩放它):-

//手动而不是addWeighted()
对于(uint ri=0;ri<480;++ri)
对于(uint ci=0;ci<640;++ci)
{
if(掩码[ri*640+ci])
{
image.at(ri,ci)[0]=image.at(ri,ci)[0]*权重_蓝;
image.at(ri,ci)[1]=image.at(ri,ci)[1]*权重_绿色;
image.at(ri,ci)[2]=image.at(ri,ci)[2]*权重;
}
}    

当我在标题和图片中输入时,我的代码示例并不清楚这一点,我的ROI不是矩形。。。它可以是任何形状。。。我确实想混合(addweighted或类似的东西),但我想避免额外的副本…抱歉,但我不知道没有克隆是否可行。您是否有一组遮罩,而不是“合并”在一起,与原始图像具有相同的尺寸?不,我的图像是640x480,我的遮罩是20x15。但如果有必要,我可以将其转换为640x480。我只想对图像的某个区域进行“添加权重”,之前必须克隆图像是愚蠢的…我喜欢你的解决方案。。。我只是希望/想可能会有和openCV函数,我不知道…我对openCV了解不多,也许有一种方法。或者,您可以将需要修改的所有像素位置存储一次(在向量中),然后再进行处理。
Mat blueImage;
Rect roi;
Mat roiInImage = blueImage(roi);
roiInImage.redirect = originalImage(roi); //don't think something like this is possible
#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;
}
//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;
        }

        }