1 | initial version |
You can't get back information you lost due to pixel saturation. All you can do is to try some synthetic reconstruction using information from neighbour like cv::inpaint function does. Just to show, below is a simple code that use uses cv::inpaint
.
//helper function
void Morphology(const Mat &imgIn,Mat &imgOut,int morpOp=MORPH_CLOSE,
int minThickess=2,int shape=MORPH_ELLIPSE)
{
int size = minThickess / 2;
Point anchor = Point(size, size);
Mat element = getStructuringElement(shape, Size(2 * size + 1, 2 * size + 1), anchor);
morphologyEx(imgIn, imgOut, morpOp, element, anchor);
}
void Main_Inpaint()
{
Mat src,blur,mask,bkMask,fgMask,dst;
vector<vector<Point> > contours;
src = imread("pixel-saturation1.png");
// remove noise
cv::GaussianBlur(src,blur,Size(),2,2);
//CREATE A MASK FOR THE SATURATED PIXEL
int minBrightness=253;
int dilateSize=20;
//convert to HSV
Mat src_hsv,brightness,saturation;
vector<Mat> hsv_planes;
cvtColor(blur, src_hsv, COLOR_BGR2HSV);
split(src_hsv, hsv_planes);
brightness = hsv_planes[2];
//get the mask
threshold(brightness,mask,minBrightness,255,THRESH_BINARY);
//dialte a bit the selection
Morphology(mask,mask,MORPH_DILATE,dilateSize);
//INPAINTING
float radius=5.0;
inpaint(src,mask,dst,radius,INPAINT_NS);
imshow("Navier-Stokes based method",dst);
inpaint(src,mask,dst,radius,INPAINT_TELEA);
imshow("Method by Alexandru Telea ",dst);
//show the selection on src
findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
drawContours(src,contours,i,Scalar(0,0,255),2);
imshow("Inpaint mask",src);
waitKey(0);
}
The result is pretty nice with 1st image but fails with your 2nd case.
I know it's a completely total different approach, but if you can control camera/acquisition, you could try to reduce the brightness/gain/shutter down to remove spotlight...
It would be easier to recover dark region if a bit of information will survive see Automated Removal of Partial Occlusion Blur for reference.
Another option is High Dynamic Range...
2 | No.2 Revision |
You can't get back information you lost due to pixel saturation. All you can do is to try some synthetic reconstruction using information from neighbour like cv::inpaint function does. Just to show, below is a simple code that use uses cv::inpaint
.
//helper function
void Morphology(const Mat &imgIn,Mat &imgOut,int morpOp=MORPH_CLOSE,
int minThickess=2,int shape=MORPH_ELLIPSE)
{
int size = minThickess / 2;
Point anchor = Point(size, size);
Mat element = getStructuringElement(shape, Size(2 * size + 1, 2 * size + 1), anchor);
morphologyEx(imgIn, imgOut, morpOp, element, anchor);
}
void Main_Inpaint()
{
Mat src,blur,mask,bkMask,fgMask,dst;
vector<vector<Point> > contours;
src = imread("pixel-saturation1.png");
// remove noise
cv::GaussianBlur(src,blur,Size(),2,2);
//CREATE A MASK FOR THE SATURATED PIXEL
int minBrightness=253;
int dilateSize=20;
//convert to HSV
Mat src_hsv,brightness,saturation;
vector<Mat> hsv_planes;
cvtColor(blur, src_hsv, COLOR_BGR2HSV);
split(src_hsv, hsv_planes);
brightness = hsv_planes[2];
//get the mask
threshold(brightness,mask,minBrightness,255,THRESH_BINARY);
//dialte a bit the selection
Morphology(mask,mask,MORPH_DILATE,dilateSize);
//INPAINTING
float radius=5.0;
inpaint(src,mask,dst,radius,INPAINT_NS);
imshow("Navier-Stokes based method",dst);
inpaint(src,mask,dst,radius,INPAINT_TELEA);
imshow("Method by Alexandru Telea ",dst);
//show the selection on src
findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size(); i++)
drawContours(src,contours,i,Scalar(0,0,255),2);
imshow("Inpaint mask",src);
waitKey(0);
}
The result is pretty nice with 1st image but fails with your 2nd case.
I know it's a completely total different approach, but if you can control camera/acquisition, you could try to reduce the brightness/gain/shutter down to remove spotlight...
It would be easier to recover dark region if a bit of information will survive see Automated Removal of Partial Occlusion Blur for reference.
Another option is High Dynamic Range...