【问题标题】:grayscale a ROI of a BGR image灰度化 BGR 图像的 ROI
【发布时间】:2016-01-12 20:04:13
【问题描述】:

我被 OpenCV 的一个小问题困住了。

我可以在我的网络摄像头捕获的图像上绘制一个矩形以绘制 ROI。我想知道是否可以对帧的这一部分进行灰度化。

我尝试了很多不同的方法来做到这一点,但我仍然无法做到。

有什么建议吗?

【问题讨论】:

    标签: c++ opencv grayscale


    【解决方案1】:

    这是一个例子

    cv::Mat image, roi_image;
    image = cv::imread("example.jpg");  
    cv::Rect r = cv::Rect(10,10, 50,50); // 'r' defines the location of ROI
    roi_image = image(r);                // select ROI 
    cvtColor(roi_image, roi_image, CV_RGB2GRAY);  //modify ROI
    imshow("Ouput", image);   // desired output image where ROI is in grayscale
    cv::waitKey(10);         // add this line so that graphics can update
    

    请注意,roi_image 是一个指向image ROI 的矩阵。如果你修改 roi_image 它也会修改image

    【讨论】:

    • 您好,感谢您的回答。事实上,我希望灰度区域显示在 BGR 图像上。这可能吗?
    • 如前所述,roi_image 指向原始图像的 ROI 区域。您对roi_image 所做的任何更改也会对原始图像中的 ROI 区域进行。因此,在代码中,image 将是仅在 ROI 位置处的灰度。那是你要的吗?你可以试试代码看看效果。
    • 感谢您的回复。不幸的是,它不起作用。我没有灰度区域。我可以在框架上绘制一个 ROI,但是当我按下按钮对该区域进行灰度化时,什么也没有发生。这是我的代码: IplImage* frame=0, gray, temp;帧 = cvQueryFrame(cam); temp = cvCloneImage(帧); cvCopy(帧,温度); if(drawing_box || box_drew){ draw_box(temp,box); } if(grayScaleOn && box_drew){ gray = cvCreateImage(cvSize(box.width,box.height), 8, 1); cvSetImageROI(temp, box); cvCvtColor(温度,灰色,CV_BGR2GRAY); cvResetImageROI(temp); cvShowImage("Cam_2_Gray", temp); }
    • 是的,我刚刚意识到我的代码不起作用。我认为这是因为灰度图像有 1 个通道,而 BGR 图像有 3 个通道。我看看能不能修复,或者你可以试试@sgar91 的建议。
    • 没错。我最终得到了一个效果很好的解决方案,您可以在下面看到它:)感谢您的宝贵时间!
    【解决方案2】:

    感谢你们的时间和耐心。 我正在阅读 O'reilly 的“Learning openCV”一书,所有示例都是使用 IplImage 类而不是 Mat 类完成的。其实我也不知道有什么区别。

    无论如何,我无法使用您的解决方案,因为我不使用任何 Mat 对象,这是我的解决方案(现在可以使用):

    while(1)
    {
     frame = cvQueryFrame(cam);
     temp = cvCloneImage(frame);
     if(!frame)break;
     cvCopy(frame,temp);
     if(drawing_box || box_drew)
      draw_box(temp,box);
    
     if(grayScaleOn && box_drew)
     {
      for(int y=box.y;y<box.y+box.height;y++)
      {
        uchar* ptr = (uchar*)(temp->imageData+y*temp->widthStep);
        for(int x=box.x;x<box.x+box.width;x++)
        {
    ptr[3*x+0] = ptr[0] * 0.114 + ptr[3*x+1]*0.587 + ptr[3*x+2]*0.299;
    ptr[3*x+1] = ptr[0] * 0.114 + ptr[3*x+1]*0.587 + ptr[3*x+2]*0.299;
    ptr[3*x+2] = ptr[0] * 0.114 + ptr[3*x+1]*0.587 + ptr[3*x+2]*0.299;
        }
      }
     cvShowImage("Output", temp);
    

    【讨论】:

    • 很高兴它现在可以工作了!您可以尝试使用较新的 Mat 数组。使用Mat 而不是Iplimage 重写此代码可能是一个很好的练习。 =)
    • 是的好主意。但我首先需要知道 Map 类到底是什么;)
    【解决方案3】:

    这是将捕获的图像 ROI 设置为灰度的粗略方法:

    cv::VideoCapture capture;
    cv::Mat frame, grayFrame, gray3;
    
    if(!capture.open(-1))
    {
        cout<<"Capture Not Opened"<<endl; return;
    }
    
    int width = capture.get(CV_CAP_PROP_FRAME_WIDTH);
    int height = capture.get(CV_CAP_PROP_FRAME_HEIGHT);
    
    cv::Rect roi(20,20,400,400); //The ROI to convert to gray
    
    cv::Mat mask = cv::Mat::zeros(height,width,CV_8U);
    for(int i = roi.y; i<roi.y + roi.height - 1; i++)
        for(int j= roi.x; j<roi.x + roi.width - 1; j++)
            mask.at<uchar>(i,j) = 1;
    
    do 
    {
        capture>>frame;
    
        if(frame.empty()) break;
    
        cv::cvtColor(frame,grayFrame,cv::COLOR_BGR2GRAY);
    
        cv::cvtColor(grayFrame, gray3, cv::COLOR_GRAY2BGR);
    
        frame.setTo(cv::Scalar::all(0),mask);
        cv::add(frame,gray3,frame,mask);
    
        cv::imshow("Image",frame);
        cv::waitKey(10);
    } 
    while (true);
    

    我找不到更简单的方法来使用蒙版操作设置图像值,因此替代方法是将 ROI 设置为零,然后将蒙版值添加到其中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 2018-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多