从一组图片中检测(并移除)划痕

时间:2015-10-29 15:39:57

标签: image opencv computer-vision

为了简化,我有一组从相机拍摄的照片。这款相机位于丙烯酸圆顶后面,这个圆顶上有划痕。图片中的划痕非常明显。 使用opencv,我试图检测并删除这些划痕。 我的第一种方法是将图片的子集相乘以创建蒙版,而不是应用inpaint蒙版。我是在正确的轨道上吗?在乘以图像之前,我可以对图像进行处理吗?

enter image description here enter image description here enter image description here enter image description here

编辑: 这是一张突出划痕enter image description here

的图片

1 个答案:

答案 0 :(得分:2)

经过几次测试后,我找到了一种可靠的方法来消除一组图像上反复出现的划痕和灰尘斑点。首先,我拍摄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将其转换为黑白。

最后一步是在带有划痕掩码的所有图像集上使用Inpaint功能。

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

以下是每一步拍摄的样本图片:

原始图片 enter image description here

此图像的轮廓 enter image description here

所有轮廓成倍增加 enter image description here

面膜被侵蚀和扩张 enter image description here

最终结果 enter image description here