如何使用 OpenCV 获得像 Cam Scanner 这样的 Magic Color 效果

新手上路,请多包涵

这是原始图像。

原始图像

凸轮扫描仪魔术色彩效果。 凸轮扫描仪效果

我对图像的过滤器。

我的过滤器

我正在改变图像的对比度。

 dst.convertTo(dst, -1, 2, 0);

然后使用高斯模糊进行平滑。

 cv::GaussianBlur(dst,result,cv::Size(0,0),3);
cv::addWeighted(dst, 1.5, result, -0.5, 0, result);

我应该怎么做才能对我的形象产生这种影响?

更新

直方图均衡后 -

 vector<Mat> channels;
Mat img_hist_equalized;
cvtColor(dst, img_hist_equalized, CV_BGR2YCrCb);
split(img_hist_equalized,channels);
equalizeHist(channels[0], channels[0]);
merge(channels,img_hist_equalized);
cvtColor(img_hist_equalized, img_hist_equalized, CV_YCrCb2BGR);

直方图均衡

原文由 mihirjoshi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 645
2 个回答

camscanner 应用程序可能正在使用一些复杂的算法来处理各种闪电情况等。但我将尝试介绍解决此类问题的基本方法,这里的基本思想是给定输入图像的 二值化,或者更 准确地说,我们可以说给定图像,如果您查看 OpenCV 文档,有很多关于对给定图像进行阈值处理的参考资料,所以让我们从 文档 开始。

  • 全局阈值:在这种方法中,我们假设前景的强度值始终低于某个值,在印刷纸张的上下文中,我们假设墨水颜色始终为黑色,纸张颜色均匀且强度大于墨水颜色,所以我们安全地假设一些阈值(比如 40),(最大值为 255)并将输入图像的阈值设置为:
    ret, thresh1 = cv2.threshold(img, 100, 255, cv2.THRESH_BINARY)

在此处输入图像描述

     ret, thresh1 = cv2.threshold(img, 130, 255, cv2.THRESH_BINARY)

在此处输入图像描述

 There are many disadvantages to this method, First of all it is **NOT** independent of intensity variance, So there is a very less chance that you can accurately estimate  a threshold value which segments text from the given image, It has very limited applications, can be only applied in case where the background paper is exactly white with minimum variation in intensity, so this process cannot be used for **Real world** images.

  • 自适应阈值:此方法涵盖了给定图像中的强度变化问题,此处对相邻像素的值进行阈值处理,因此使用此方法成功捕获了从较低强度到较高强度的转换,反之亦然:
    thresh = cv2.adaptiveThreshold(original_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)

在此处输入图像描述

 *Further Work*: You may work on various techniques of denoising the binary image, to remove the dots, Or have a look at removing the salt and pepper noise from the image.

  • Otu 的二值化:这是另一种很好的方法,可以智能地计算最大值之间的阈值,在某些情况下它可能工作得很好,但在你的情况下它似乎失败了。
    ret2,thresh = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

在此处输入图像描述

它基本上执行相同的 全局阈值 处理,但现在自动计算阈值,使阈值位于 2 个峰值之间,从而将墨水从纸张中分割出来。

推荐方法: 我想最好的方法是 _自适应阈值_,你可以尝试一些其他的预处理技术,如 锐化图像直方图均衡 等,并分析它如何创建更真实的输出,你也可以尝试做一些帖子 图像去噪形态学运算 等处理

我尝试了图像的去噪,发现它比其他方法更有效,

 denoised = cv2.fastNlMeansDenoising(thresh, 11, 31, 9) # you may experiment with the constants here

在此处输入图像描述

但我欢迎您尝试上述方法的各种组合,看看哪一种适用于所有情况。

注意: 上述技术可能适用于色彩较少的图像。但是,这是另一个 很好的答案,它可以解决彩色图像的情况。

原文由 ZdaR 发布,翻译遵循 CC BY-SA 4.0 许可协议

我已经编写了执行此类操作的代码,尽管不是使用 OpenCV。

通常,我会分析直方图,根据直方图估计“白色”和“黑色”是什么,然后缩放图像值,使黑色缩放到 0 以下,白色缩放到 1 以上(或 255,具体取决于您的表示) ,最后钳制颜色值。

但是,使用 OpenCV 可能会有更简单的方法。在应用对比度过滤器之前尝试在裁剪页面上使用直方图均衡 - 这应该以更一致的方式分散像素值,以便在更多情况下调整对比度更可靠。您可以尝试使用 局部 直方图均衡来帮助减轻由于光照导致的裁剪图像上的渐变,但这可能会导致页面空白区域出现问题。

原文由 Kaganar 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题