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