从一组图片中检测(并去除)划痕
Detect (and remove) scratches from a set of pictures
为了简单起见,我有一组用相机拍摄的照片。这个相机在一个丙烯酸圆顶后面,这个圆顶上有划痕。图片上的划痕非常明显。
使用 opencv,我试图检测并删除这些划痕。
我的第一种方法是乘以图片的子集来创建一个蒙版,而不是应用修复蒙版。我在正确的轨道上吗?在相乘之前我可以对图像进行处理吗?
编辑:
这是一张突出划痕的图片
经过几次测试,我找到了一种可靠的方法来消除一组图像上反复出现的划痕和灰尘点。首先,我拍摄 10 到 15 张图片的子集,打开它们,然后应用 sobel derivatives 提取轮廓。
private Image<Gray, byte> GetImageContours(String strImage)
{
Image<Gray, Byte> img = new Image<Gray, byte>(strImage);
Image<Gray, float> gradx = img.Sobel(1, 0, 5);
Image<Gray, Byte> gradxconv = gradx.ConvertScale<Byte>(1, 0);
Image<Gray, float> grady = img.Sobel(0, 1, 5);
Image<Gray, Byte> gradyconv = grady.ConvertScale<Byte>(1, 0);
Image<Gray, Byte> imgContours = gradxconv.AddWeighted(gradyconv, 0.5, 0.5, 0);
img.Dispose();
gradx.Dispose();
grady.Dispose();
gradxconv.Dispose();
gradyconv.Dispose();
return imgContours;
}
然后,我将图像转换回 16 位深度,然后将它们全部相乘。这应该只给我划痕的图像。
为了创建划痕蒙版,我将这张图片腐蚀了一次,然后将其放大了 10 倍。之后,我通过 运行 一个阈值为 40 的 TresholdBinary 将其转换为黑白。
最后一步是对所有带有划痕蒙版的图像集使用修复功能。
Image<Gray, float> _img1 = img1.Convert<Gray, float>();
Image<Gray, float> _img2 = img2.Convert<Gray, float>();
Image<Gray, float> _img3 = img3.Convert<Gray, float>();
Image<Gray, float> _img4 = img4.Convert<Gray, float>();
Image<Gray, float> _img5 = img5.Convert<Gray, float>();
Image<Gray, float> _img6 = img6.Convert<Gray, float>();
Image<Gray, float> _img7 = img7.Convert<Gray, float>();
Image<Gray, float> _img8 = img8.Convert<Gray, float>();
Image<Gray, float> _img9 = img9.Convert<Gray, float>();
Image<Gray, float> _img10 = img10.Convert<Gray, float>();
Image<Gray, float> _img11 = img11.Convert<Gray, float>();
Image<Gray, float> _img12 = img12.Convert<Gray, float>();
Image<Gray, float> imgMask = _img1.Mul(_img2).Mul(_img3).Mul(_img4).Mul(_img5).Mul(_img6).Mul(_img7).Mul(_img8).Mul(_img9).Mul(_img10).Mul(_img11).Mul(_img12).Erode(1);
Image<Gray, Byte> imgMask2 = imgMask.Convert<Gray, Byte>();
Image<Gray, Byte> imgMask3 = imgMask2.Dilate(10).ThresholdBinary(new Gray(40), new Gray(255));
//img is one of the original images to remove scratches on
ImageViewer viewer3 = new ImageViewer(img.InPaint(imgMask3, 3), "image3");
viewer3.Show();
以下是每一步拍摄的示例图片:
原图
这张图片的轮廓
所有轮廓相乘
蒙版被腐蚀和膨胀
最终结果
为了简单起见,我有一组用相机拍摄的照片。这个相机在一个丙烯酸圆顶后面,这个圆顶上有划痕。图片上的划痕非常明显。 使用 opencv,我试图检测并删除这些划痕。 我的第一种方法是乘以图片的子集来创建一个蒙版,而不是应用修复蒙版。我在正确的轨道上吗?在相乘之前我可以对图像进行处理吗?
编辑:
这是一张突出划痕的图片
经过几次测试,我找到了一种可靠的方法来消除一组图像上反复出现的划痕和灰尘点。首先,我拍摄 10 到 15 张图片的子集,打开它们,然后应用 sobel derivatives 提取轮廓。
private Image<Gray, byte> GetImageContours(String strImage)
{
Image<Gray, Byte> img = new Image<Gray, byte>(strImage);
Image<Gray, float> gradx = img.Sobel(1, 0, 5);
Image<Gray, Byte> gradxconv = gradx.ConvertScale<Byte>(1, 0);
Image<Gray, float> grady = img.Sobel(0, 1, 5);
Image<Gray, Byte> gradyconv = grady.ConvertScale<Byte>(1, 0);
Image<Gray, Byte> imgContours = gradxconv.AddWeighted(gradyconv, 0.5, 0.5, 0);
img.Dispose();
gradx.Dispose();
grady.Dispose();
gradxconv.Dispose();
gradyconv.Dispose();
return imgContours;
}
然后,我将图像转换回 16 位深度,然后将它们全部相乘。这应该只给我划痕的图像。 为了创建划痕蒙版,我将这张图片腐蚀了一次,然后将其放大了 10 倍。之后,我通过 运行 一个阈值为 40 的 TresholdBinary 将其转换为黑白。
最后一步是对所有带有划痕蒙版的图像集使用修复功能。
Image<Gray, float> _img1 = img1.Convert<Gray, float>();
Image<Gray, float> _img2 = img2.Convert<Gray, float>();
Image<Gray, float> _img3 = img3.Convert<Gray, float>();
Image<Gray, float> _img4 = img4.Convert<Gray, float>();
Image<Gray, float> _img5 = img5.Convert<Gray, float>();
Image<Gray, float> _img6 = img6.Convert<Gray, float>();
Image<Gray, float> _img7 = img7.Convert<Gray, float>();
Image<Gray, float> _img8 = img8.Convert<Gray, float>();
Image<Gray, float> _img9 = img9.Convert<Gray, float>();
Image<Gray, float> _img10 = img10.Convert<Gray, float>();
Image<Gray, float> _img11 = img11.Convert<Gray, float>();
Image<Gray, float> _img12 = img12.Convert<Gray, float>();
Image<Gray, float> imgMask = _img1.Mul(_img2).Mul(_img3).Mul(_img4).Mul(_img5).Mul(_img6).Mul(_img7).Mul(_img8).Mul(_img9).Mul(_img10).Mul(_img11).Mul(_img12).Erode(1);
Image<Gray, Byte> imgMask2 = imgMask.Convert<Gray, Byte>();
Image<Gray, Byte> imgMask3 = imgMask2.Dilate(10).ThresholdBinary(new Gray(40), new Gray(255));
//img is one of the original images to remove scratches on
ImageViewer viewer3 = new ImageViewer(img.InPaint(imgMask3, 3), "image3");
viewer3.Show();
以下是每一步拍摄的示例图片:
原图
这张图片的轮廓
所有轮廓相乘
蒙版被腐蚀和膨胀
最终结果