Image processing 模糊图像的自适应阈值

Image processing 模糊图像的自适应阈值,image-processing,opencv,threshold,Image Processing,Opencv,Threshold,我有一张非常模糊的432x432的数独拼图,它的自适应阈值不好(取5x5像素块大小的平均值,然后减去2): 正如你所看到的,数字有点失真,有很多破损,一些5s融合成6s,6s融合成8s。而且,这里有很多噪音。为了修复噪声,我必须使用高斯模糊使图像更加模糊。然而,即使是相当大的高斯核和自适应阈值块大小(21x21,减去2)也无法消除所有中断,并将数字融合在一起,甚至更严重: 我还尝试过在阈值化后放大图像,这与增加块大小的效果类似;不管怎样,这都没什么用。我还应该试试什么?看看。除Gaussia

我有一张非常模糊的432x432的数独拼图,它的自适应阈值不好(取5x5像素块大小的平均值,然后减去2):

正如你所看到的,数字有点失真,有很多破损,一些5s融合成6s,6s融合成8s。而且,这里有很多噪音。为了修复噪声,我必须使用高斯模糊使图像更加模糊。然而,即使是相当大的高斯核和自适应阈值块大小(21x21,减去2)也无法消除所有中断,并将数字融合在一起,甚至更严重:

我还尝试过在阈值化后放大图像,这与增加块大小的效果类似;不管怎样,这都没什么用。我还应该试试什么?

看看。除GaussianBlur外,还有
medianBlur
bilateralFilter
,您也可以使用它们来降低噪音。我从您的源图像(右上角)中获取了此图像:

更新:以及我在删除小轮廓后得到的以下图像:


更新:您还可以锐化图像(例如,使用
Laplacian
)。看看。

一个很好的解决方案是使用形态学闭合使亮度均匀,然后使用常规(非自适应)大津阈值:

// Divide the image by its morphologically closed counterpart
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_ELLIPSE, new Size(19,19));
Mat closed = new Mat();
Imgproc.morphologyEx(image, closed, Imgproc.MORPH_CLOSE, kernel);

image.convertTo(image, CvType.CV_32F); // divide requires floating-point
Core.divide(image, closed, image, 1, CvType.CV_32F);
Core.normalize(image, image, 0, 255, Core.NORM_MINMAX);
image.convertTo(image, CvType.CV_8UC1); // convert back to unsigned int

// Threshold each block (3x3 grid) of the image separately to
// correct for minor differences in contrast across the image.
for (int i = 0; i < 3; i++) {
    for (int j = 0; j < 3; j++) {
        Mat block = image.rowRange(144*i, 144*(i+1)).colRange(144*j, 144*(j+1));
        Imgproc.threshold(block, block, -1, 255, Imgproc.THRESH_BINARY_INV+Imgproc.THRESH_OTSU);
    }
}
//将图像除以其形态上闭合的对应图像
Mat kernel=Imgproc.getStructuringElement(Imgproc.morp_椭圆,新大小(19,19));
垫关闭=新垫();
Imgproc.morphologyEx(图像,闭合,Imgproc.MORPH\u闭合,内核);
image.convertTo(image,CvType.CV_32F);//除法需要浮点运算
Core.divide(image,closed,image,1,CvType.CV_32F);
规格化(image,image,0,255,Core.NORM\u MINMAX);
image.convertTo(image,CvType.CV_8UC1);//转换回无符号整数
//将图像的每个块(3x3网格)分别设置为阈值
//纠正图像中对比度的细微差异。
对于(int i=0;i<3;i++){
对于(int j=0;j<3;j++){
Mat block=image.rowRange(144*i,144*(i+1)).colRange(144*j,144*(j+1));
Imgproc.threshold(块,块,-1255,Imgproc.THRESH\u BINARY\u INV+Imgproc.THRESH\u OTSU);
}
}
结果:


始终应用高斯函数以获得更好的结果

cvAdaptiveThreshold(original_image, thresh_image, 255,
            CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, 11, 2);

你看到了吗?我最近确实看到了这一点,但对于凸性代码(我最后没有费心实现),而不是规范化代码。我现在肯定要看一看。你能通过假设一个结构良好的谜题来添加非图像处理策略吗?如果是这样,您可以应用一些不依赖于图像质量的其他规则。例如,对于OCR结果置信度较低的单元格,您可以在三个房间中分别检查相关单元格的高置信度数字,这可以限制低置信度单元格的可能性。您也可以使用高置信度单元格部分解决此难题,这将增加约束条件。@DaveK我认为这是一个非常有创意的解决方案。我喜欢使用附近的细胞来提高自信的想法。我认为你甚至不需要部分解决这个难题,即使是简单的DFS解决只需要很少的时间。然后,您可以简单地采用您得到的第一个解决方案,并假设它是正确的。再加上一些并行处理,每个核心采用不同的假设板,很快就会有一个解决方案。我正在使用OpenCV的HoG和SVM对数字进行分类。我不知道有可能从这个界面获得信任。即使我可以,我宁愿在检测过程中提高图像质量。好主意,如果其他的都失败了,我可以考虑一下。谢谢你的建议!这比原来的好,但不能充分解决数字中断的问题。如何合并块?高斯阈值并不总是导致更好的结果。