-2

I am stuck with a little problem with OpenCV.

I am able to draw a rectangle on my webcam's capture in order to draw a ROI. I would like to know if it is possible to grayscale this part of the frame.

I tried many different ways to do it, but I still can't make it.

Any suggestions?

Ajay
  • 18,086
  • 12
  • 59
  • 105
kevin labille
  • 53
  • 1
  • 1
  • 6

3 Answers3

0

Here's an example

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

Note that roi_image is a matrix that is pointing to the ROI of image. If you modify roi_image it will also modify image.

Alexey
  • 5,898
  • 9
  • 44
  • 81
  • Hello, thanks for your answer. In fact, I would like the grayscale region to be displayed over the BGR image. Is that possible ? – kevin labille Mar 21 '13 at 04:03
  • As I mentioned, `roi_image` points to the ROI area of the original image. Any change that you make to `roi_image` is also made to ROI area in the original image. So, in the code, `image` will be the grayscale only at ROI location. Is that what you want? You can try the code and see the result. – Alexey Mar 21 '13 at 13:37
  • Thank you for your reply. Unfirtunately, it doesn't work. I get no grayscale area. I'm able to draw a ROI on the frame but when I hit the button to grayscale that area, nothing happens. Here is my code : IplImage* frame=0, gray, temp; frame = cvQueryFrame(cam); temp = cvCloneImage(frame); cvCopy(frame,temp); 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(temp,gray,CV_BGR2GRAY); cvResetImageROI(temp); cvShowImage("Cam_2_Gray", temp); } – kevin labille Mar 21 '13 at 14:15
  • Yes, I just realized that my code won't work. I think this is because grayscale image has 1 channel and BGR image has 3 channels. I see if it can be fixed, or you may try the suggestion by @sgar91. – Alexey Mar 21 '13 at 14:49
  • Yeah exactly. I ended up with a solution that works great, you can see it below :) Thanks for your time ! – kevin labille Mar 21 '13 at 15:05
0

Here is a crude way to set captured image ROI to grayscale:

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);

I couldn't find a simpler way to set image values using masked operation, so the alternate is to set the ROI to zero, and add the masked values to it.

sgarizvi
  • 16,623
  • 9
  • 64
  • 98
0

Thanks for your time and patience guys. I'm reading the "Learning openCV" book from O'reilly and all the examples are done with the IplImage class instead of the Mat class. Actually, I don't even know what's the difference.

Anyway, I couldn't use your solution since I do not use any Mat object, here is my solution (it works now) :

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);
kevin labille
  • 53
  • 1
  • 1
  • 6
  • glad it works now! You can try to use a newer Mat array. Rewriting this code using `Mat` instead of `Iplimage` could be a good exercise. =) – Alexey Mar 21 '13 at 15:10
  • yeah good idea. But I need to know what is exactly the Map class first ;) – kevin labille Mar 21 '13 at 15:29