0

What I'm currently doing is loading an image of a face into a Mat, setting the centre point X and Y coordinates of each eye, creating a circle around each of the eyes, setting the ROI to the circles around the eyes (using a Rect and setting a mask), and lowering the red value in the eye images.

My problem is around merging the corrected eye (with lowered red colour) back onto the original image because the corrected eyes have a black mask. I'm not sure how to get rid of the black mask.

I'm currently stuck on a bit of OpenCV code which has gotten me to this point:

Original image:

Extracted eye with black mask:

Corrected eye:

Current result displaying my problem:

This is a continuation from my thread here: Getting ROI from a Circle/Point

My understanding is that you cannot create a circular ROI, thus why I have gone with the Rect ROI and black mask. A normal Rect does not suffice.

Any advice is much appreciated!! Thank you.

Community
  • 1
  • 1
LKB
  • 1,020
  • 5
  • 22
  • 46
  • 1
    hehe, feeling a bit responsible for your current trouble. ;) what if you *check* the croppedEye image (with mask, to get rid of the skin parts), but *write_to/correct* the cloneRoi ( or the roi even, you would not have to write it back ) and use that for the copyTo() ? – berak Oct 13 '14 at 08:05
  • Hey @berak! Nono, you have helped me so much! I get what you're saying now!! This is what I have currently (quickly changed code): http://i.imgur.com/4CmL2KJ.jpg I think he was in a slight accident... hah. Possibly using wrong eye, will check now. – LKB Oct 13 '14 at 08:11
  • 1
    Yep, I was using the wrong eye, heh. :) – LKB Oct 13 '14 at 08:18

2 Answers2

3

you could use the masked roi image for testing pixels, but write into your real image:


 cv::Mat plotImage;
    int radius = 15;
    float threshold = 1.8;

    plotImage = cv::imread("C:/temp/debug.jpg", cv::IMREAD_COLOR);

    cv::Point leftEye(person.GetLeftEyePoint().X, person.GetLeftEyePoint().Y);
    cv::Point rightEye(person.GetRightEyePoint().X, person.GetRightEyePoint().Y);

    //get the Rect containing the circle
    cv::Rect r(leftEye.x-radius, leftEye.y-radius, radius*2, radius*2);
    //obtain the image ROI
    cv::Mat roi(plotImage, r);
    //make a black mask, same size
    cv::Mat mask(roi.size(), roi.type(), cv::Scalar::all(0));
    //with a white filled circle in it
    cv::circle(mask, cv::Point(radius, radius), radius, cv::Scalar::all(255), -1);
    //combine roi & mask
    cv::Mat croppedEye = roi&mask;

    //conduct red eye detection/removal on croppedEye
    int count = 0;
    for(int y=0;y<croppedEye.rows;y++)
    {
            for(int x=0;x<croppedEye.cols;x++)
            {
                    double b = croppedEye.at<cv::Vec3b>(y, x)[0];
                    double g = croppedEye.at<cv::Vec3b>(y, x)[1];
                    double r = croppedEye.at<cv::Vec3b>(y, x)[2];

                    double redIntensity = r / ((g + b) / 2);

                    //currently causes issues with non-red-eye images
                    if (redIntensity >= threshold)
                    {
                            double newRedValue = (g + b) / 2;
                            cv::Vec3b pixelColor(newRedValue,g,b);
                            //
                            // here's the trick now, just write back to the original image ;)
                            //
                            roi.at<cv::Vec3b>(cv::Point(x,y)) = pixelColor;
                            count++;
                    }
            }
    }

    cv::imwrite("C:\\temp\\test.jpg", plotImage);

enter image description here

berak
  • 39,159
  • 9
  • 91
  • 89
0

Check this post. Transparent mask

if (imageMask.at<Vec3b>(xx,yy)[0] < 10)
// This mean If the color of mask in one channel is < 10 replace the original Image
                              {
                                                    // Copy to original image on (y,x) places  the pixel of xx,yy mask
    OriginalImage.at<Vec3b>(y,x)[0] =  imageMask .at<Vec3b>(xx,yy)[0];
    OriginalImage.at<Vec3b>(y,x)[1] =  imageMask .at<Vec3b>(xx,yy)[1];
    OriginalImage.at<Vec3b>(y,x)[2] =  imageMask .at<Vec3b>(xx,yy)[2]; 
                               }
globalex
  • 549
  • 3
  • 11