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

时间:2015-10-02 18:02:35

标签: android c++ c opencv android-ndk

这是原始图片。

Orignal Image

Cam Camner Magic color effect。Cam Scanner effect

我在图片上的过滤器。

My filter

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

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

Histogram Equilization

5 个答案:

答案 0 :(得分:7)

camscanner应用程序可能正在使用一些复杂的算法来处理各种闪电案例等。但我会尝试涵盖这种问题的基本方法,这里的基本思路是给定输入的二值化图像,或者更确切地说,我们可以说阈值给定的图像,如果你看一下OpenCV文档,有很多参考文献给定位图像设定阈值,那么让我们从documentation开始

  • 全局阈值:在这种方法中,我们假设前景的强度值总是低于某个值。在打印纸张的上下文中,我们假设墨水颜色总是黑色并且纸张颜色均匀且强度大于墨水颜色的强度,因此我们安全地假设某个阈值(例如40),(最大值为255)并将输入图像阈值设为:

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

    enter image description here

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

    enter image description here

    这种方法有许多缺点,首先它是 NOT ,与强度方差无关,因此您可以准确估计一个阈值来分割给定文本的概率很小。图像,应用非常有限,只能在背景纸为白色且强度变化最小的情况下应用,因此此过程不能用于真实世界图像。

    < / LI>
  • 自适应阈值:此方法涵盖给定图像中的强度变化问题,此处对相邻像素的值进行阈值处理,因此从较低强度到较高强度的转换,反之亦然使用此方法成功捕获:

    thresh = cv2.adaptiveThreshold(original_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
    

    enter image description here

    进一步的工作:您可以使用各种技术去除二值图像的去噪,去除点,或者看看从图像中去除盐和胡椒的噪音。

    < / LI>
  • Otu的二值化:这是另一个很好的方法,智能地计算最大值之间的阈值,它可能在某些情况下工作得非常好,但它似乎失败了你的情况。

    ret2,thresh = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
    

    enter image description here

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

推荐方法: 我想最好的方法是自适应阈值,您可以尝试其他预处理技术,如sharpening imageHistogram Equalisation等,并分析它如何创建更逼真的输出,您也可以尝试进行一些后期处理,例如denoising the imageMorphological operations

我尝试对图像进行去噪,发现它对其他方法更有效,

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

enter image description here

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

答案 1 :(得分:5)

一种非常简单但有效的处理此类图像的方法是平场校正。

首先,通过对原始图像F应用非常强模糊滤镜来生成“伪”平面场图像I。 然后,将IF的平均值相乘,然后将结果图像除以F(逐像素)以得到校正后的图像C。乘法只是为了保持整体亮度,而除法就是魔术发生的地方。

基本上是这样的:C = (I * mean(F)) / F

生成的校正图像C将去除大部分(如果不是全部)不需要的大规模照明和颜色。然后剩下要做的就是进行一些对比度拉伸,您得到的结果与提供的参考图像非常相似。 (灰度,高对比度,但没有阈值)

如果您想知道所提供图像的结果如何...

首先是平面场:

flat field

然后校正图像:

corrected image

最后,在增加对比度之后:

increased contrast

最困难的部分是使平坦区域正确,因为您希望对其进行足够的模糊处理以消除文本,同时又要尽可能保留背景。非线性过滤器(例如中值)可以在这种情况下提供帮助。

答案 2 :(得分:3)

我已经使用 Photoshop 找出实现扫描效果所需的编辑技术。

在Photoshop中,可以使用“色阶”功能提供的“设置白点”和“设置黑点”操作来实现扫描效果。这两种操作的结合导致了在各种移动应用中经常被视为“神奇色彩”的扫描效果。

除此之外,高通滤波器还可以与上述两种操作一起使用,以达到一些令人兴奋的效果,例如去除阴影。

在“黑白”模式下扫描文档是通过使用 OpenCV 在 LAB 色彩空间中处理图像来实现的。

可以使用各种阈值技术和一些基本的数学运算在 OpenCV 中实现上述操作。

您可以通过 this repository 全面了解我想说的内容。

我在上面的 repo 中为该项目添加了完整的 wiki 文档。

这个答案可能看起来不是很丰富,但由于 repo 进行了详细的讨论,所以我保持这篇文章简短。

我们可以使用这些技术实现的结果示例: Image in top right corner and the image below it are the inputs whereas other images are output for various scan modes

此图中的标记有助于我们了解 GitHub 存储库中讨论的每种模式的输出类型: Markings in this image helps us to understand the type of output from each mode discussed in the GitHub repo

答案 3 :(得分:1)

我编写的代码执行此类操作,但不是OpenCV。

通常情况下,我会分析直方图,根据直方图估算“白色”和“黑色”,然后缩放图像值,使黑色缩放到0以下,白色缩放到1以上(或255取决于你的代表),最后夹住颜色值。

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

答案 4 :(得分:1)

我意识到我在游戏中有点晚了,但我找到了这个很棒的简单解决方案:

src.convertTo(dst, -1, 1.9, -80);
如果您在处理管道中工作,

src和dst可以是相同的图像。