当前位置: 首页 > 知识库问答 >
问题:

模糊图像阈值-第2部分

爱茂勋
2023-03-14

如何设置模糊图像的阈值以使数字尽可能清晰?

在之前的一篇文章中,我尝试自适应地对模糊的图像进行阈值化(左),这导致数字失真和断开连接(右):

从那时起,我尝试使用本文中描述的形态学关闭操作来使图像的亮度均匀:

如果我自适应地设置此图像的阈值,则不会得到明显更好的结果。但是,由于亮度大致一致,我现在可以使用普通阈值:

这比以前好多了,但我有两个问题:

  1. 我必须手动选择阈值。虽然关闭操作会产生均匀的亮度,但其他图像的亮度级别可能会有所不同
  2. 如果阈值水平略有变化,图像的不同部分效果会更好。例如,左上角的9和7部分褪色,应具有较低的阈值,而一些6融合为8,应具有较高的阈值

我认为返回到自适应阈值,但使用非常大的块大小(图像的1/9)可以解决这两个问题。相反,我最终得到了一个奇怪的“光环效应”,图像的中心要亮得多,但边缘与正常阈值图像大致相同:

编辑:雷米建议从形态学上打开这篇文章右上角的阈值图像。这不太管用。使用椭圆核时,只有3x3足够小,可以避免完全抹去图像,即使这样,数字中也会出现明显的破损:

编辑2:mmgp建议使用维纳滤波器来消除模糊。我将OpenCV中用于维纳过滤的代码改编为OpenCV4Android,但这会使图像更加模糊!以下是使用我的代码和5x5内核过滤前后的图像:

这是我的改编代码,它将过滤到位:

private void wiener(Mat input, int nRows, int nCols) { // I tried nRows=5 and nCols=5

    Mat localMean = new Mat(input.rows(), input.cols(), input.type());
    Mat temp = new Mat(input.rows(), input.cols(), input.type());
    Mat temp2 = new Mat(input.rows(), input.cols(), input.type());

    // Create the kernel for convolution: a constant matrix with nRows rows 
    // and nCols cols, normalized so that the sum of the pixels is 1.
    Mat kernel = new Mat(nRows, nCols, CvType.CV_32F, new Scalar(1.0 / (double) (nRows * nCols)));

    // Get the local mean of the input.  localMean = convolution(input, kernel)
    Imgproc.filter2D(input, localMean, -1, kernel, new Point(nCols/2, nRows/2), 0); 

    // Get the local variance of the input.  localVariance = convolution(input^2, kernel) - localMean^2 
    Core.multiply(input, input, temp);  // temp = input^2
    Imgproc.filter2D(temp, temp, -1, kernel, new Point(nCols/2, nRows/2), 0); // temp = convolution(input^2, kernel)
    Core.multiply(localMean, localMean, temp2); //temp2 = localMean^2
    Core.subtract(temp, temp2, temp); // temp = localVariance = convolution(input^2, kernel) - localMean^2  

    // Estimate the noise as mean(localVariance)
    Scalar noise = Core.mean(temp);

    // Compute the result.  result = localMean + max(0, localVariance - noise) / max(localVariance, noise) * (input - localMean)

    Core.max(temp, noise, temp2); // temp2 = max(localVariance, noise)

    Core.subtract(temp, noise, temp); // temp = localVariance - noise
    Core.max(temp, new Scalar(0), temp); // temp = max(0, localVariance - noise)

    Core.divide(temp, temp2, temp);  // temp = max(0, localVar-noise) / max(localVariance, noise)

    Core.subtract(input, localMean, input);  // input = input - localMean
    Core.multiply(temp, input, input); // input = max(0, localVariance - noise) / max(localVariance, noise) * (input - localMean)
    Core.add(input, localMean, input); // input = localMean + max(0, localVariance - noise) / max(localVariance, noise) * (input - localMean)
}

共有3个答案

储志业
2023-03-14

如果你愿意花一些时间在它上面,有一些去模糊技术可以用来在处理之前将图片锐化。OpenCV中还没有任何内容,但如果这是一种成败攸关的东西,您可以添加它。

有很多关于这个主题的文献:http://www.cse.cuhk.edu.hk/~ leojia/项目/运动\去模糊/索引。htmlhttp://www.google.com/search?q=motion消除模糊

OpenCV邮件列表上的一些喋喋不休:http://tech.groups.yahoo.com/group/OpenCV/message/20938

你看到的奇怪的“光晕效应”可能是由于OpenCV在自适应阈值位于/接近图像边缘时假设颜色为黑色,并且它使用的窗口“挂在”边缘到非图像区域。有一些方法可以纠正这个问题,很可能你会制作一个比相机图像高至少两个完整块大小的临时图像。然后将相机图像复制到它的中间。然后将临时图像的周围“空白”部分设置为相机图像的平均颜色。现在,当您执行自适应阈值时,边缘处/附近的数据将更接近准确。它不会是完美的,因为它不是真实的图片,但它会产生比OpenCV假设的黑色更好的结果。

韦星文
2023-03-14

我尝试过分别为每个3x3框设置阈值,使用Otsu的算法(CV_OTSU-谢谢remi!)来确定每个框的最佳阈值。这比为整个图像设置阈值要好一点,而且可能更健壮一点。

不过,我们欢迎更好的解决方案。

詹甫
2023-03-14

您可以尝试以下提示:

>

  • 在原始阈值图像(第一张图片右侧有噪声的图像)中应用形态学开口。您应该消除大部分背景噪音,并能够重新连接数字。

    使用原始图像的不同预处理而不是形态关闭,例如中值滤波(倾向于模糊边缘)或双边滤波,这将更好地保留边缘,但计算速度较慢。

    就阈值而言,您可以使用cv::阈值中的CV_OTSU标志来确定全局阈值的最佳值。局部阈值可能仍然更好,但应该更好地使用双边或中值滤波器

  •  类似资料:
    • 我有一张非常模糊的432x432的数独拼图,它的自适应阈值不好(取5x5像素块大小的平均值,然后减去2): 正如你所看到的,数字有点失真,有很多破损,一些5s融合成6s,6s融合成8s。此外,还有大量噪音。为了修复噪声,我必须使用高斯模糊使图像更加模糊。然而,即使是相当大的高斯核和自适应阈值块大小(21x21,减去2)也无法消除所有中断,并将数字融合到一起,甚至更严重: 我还尝试过在阈值化后放大图

    • 图像阈值 目标 在本教程中,您将学习简单阈值处理,自适应阈值处理,Otsu阈值处理等。 您将学习以下函数:cv2.threshold, cv2.adaptiveThreshold等。 一、单的阈值 在这里,事情是直截了当的。如果像素值大于阈值,则为其分配一个值(可以是白色),否则为其分配另一个值(可以是黑色)。使用的函数是cv2.threshold。第一个参数是源图像,它应该是灰度图像。第二个参数

    • 目标 在本教程中,您将学习简单阈值,自适应阈值和Otsu阈值。 你将学习函数cv.threshold和cv.adaptiveThreshold。 简单阈值 在这里,问题直截了当。对于每个像素,应用相同的阈值。如果像素值小于阈值,则将其设置为0,否则将其设置为最大值。函数cv.threshold用于应用阈值。第一个参数是源图像,它应该是灰度图像。第二个参数是阈值,用于对像素值进行分类。第三个参数是分

    • 我在试着模糊图像 它会模糊图像,但不是图像的所有部分。 我所缺少的地方,这样它就会模糊完整的图像。没有任何路径。

    • 什么是快速可靠的方法来阈值图像可能模糊和不均匀的亮度? 示例(模糊但亮度一致): 因为不能保证图像具有均匀的亮度,所以使用固定阈值是不可行的。自适应阈值工作正常,但由于模糊,它会在特征中造成中断和扭曲(这里,重要的特征是数独数字): 我也尝试过使用直方图均衡化(使用OpenCV的均衡器函数)。它在不减少亮度差异的情况下增加对比度。 我找到的最佳解决方案是将图像按其形态闭合(归功于这篇文章)进行分割

    • 问题内容: 我正在尝试在Java游戏中实现模糊机制。如何在运行时创建模糊效果? 问题答案: 请参阅/ Google“卷积滤镜”,这是一种根据周围像素值更改像素值的方法。因此,除了模糊之外,您还可以进行图像锐化和寻线。