OpenCV灰度忽略红色

时间:2018-06-08 17:27:16

标签: c# android opencv image-processing xamarin.android

我正在制作识别数字(OCR)的应用程序,所以我需要为它准备imamge。当我将照片拍到蓝色,绿色,黄色或其他颜色时没有问题,但是在OpenCV中灰度级后红色数字变得如此灰暗,这些数字无法识别。

原始图片: enter image description here

灰度后的图像(黄色和红色数字): enter image description here

阈值后的图像:

enter image description here

如你所见,红色数字消失后。

以下是我使用的代码片段:

mat.ConvertTo(mat, CvType.Cv8uc1);
Imgproc.CvtColor(mat, mat, Imgproc.ColorBgr2gray);
Imgproc.Threshold(mat, mat, 127, 255, Imgproc.ThreshBinary);

任何解决方案?

2 个答案:

答案 0 :(得分:3)

正如我在评论中提到的,你可以对每个颜色通道R,G,B执行Otsu阈值。

蓝色通道的Otsu门槛:

enter image description here

绿色通道的Otsu门槛:

enter image description here

红色通道的Otsu阈值:

enter image description here

最后,我添加了以上所有内容以获得以下结果:

enter image description here

我只使用了以下功能:

  1. cv2.threshold()

  2. cv2.add()

  3. 更新

    <强>代码

    import os
    import cv2
    import numpy as np
    
    #--- performs Otsu threshold ---
    def threshold(img, st):
        ret, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
        cv2.imwrite(os.path.join(path, 'res_' + str(st) + '.jpg'), thresh) 
        return  thresh
    
    path = r'C:\Users\Desktop'
    filename = 'digits.jpg'
    
    img = cv2.imread(os.path.join(path, filename))
    img = cv2.resize(img, (0, 0), fx = 0.5, fy = 0.5)   #--- resized the image because it was to big 
    cv2.imshow('Original', img)
    
    #--- see each of the channels individually ---
    cv2.imshow('b', img[:,:,0])
    cv2.imshow('g', img[:,:,1])
    cv2.imshow('r', img[:,:,2])
    
    m1 = threshold(img[:,:,0], 1)   #--- threshold on blue channel
    m2 = threshold(img[:,:,1], 2)   #--- threshold on green channel
    m3 = threshold(img[:,:,2], 3)   #--- threshold on red channel
    
    #--- adding up all the results above ---
    res = cv2.add(m1, cv2.add(m2, m3))
    
    cv2.imshow('res', res)
    cv2.imwrite(os.path.join(path, 'res.jpg'), res)
    
    cv2.waitKey()
    cv2.destroyAllWindows()
    

答案 1 :(得分:2)

@Jeru Luke的解决方案对于各种输入图像应该相当稳健。但是如果你需要原始速度,你可能会想到一个简单的亮度/对比度操作,然后进行全局阈值处理。

如果你使用计算上便宜的亮度和对比度,你可以让背景变成全黑,然后使用全局阈值来获得漂亮的二值化图像。

照片编辑器(Photoshop,Gimp等)经常使用±127的亮度/对比度。用于同时添加亮度(b)和对比度(c)的数学格式是

  

img =(1 + c / 127)* img +(b-c)

如果您可以从C#访问mat,则可以使用cv.mat.convertTo功能:

cv.Mat.convertTo( OutputArray, cv.CV_8U, 1+c/127, b-c)

对于你的图像,我使用了b = -45和c = +45

然后转换为灰度和二值化(我在图像上使用了50的阈值)

<强>更新

OP被标记为C#。但是我们很多人都使用Python。在Python中,我们无法访问Mat。但是,我们可以使用cv2.addWeighted函数:

  

dst = src1 * alpha + src2 * beta + gamma

如果我们设置beta = 0,那么这相当于cv.Mat.convertTo缩放。这似乎比在Numpy中进行矩阵运算更快。 Numpy有点慢,因为我们必须做一些额外的事情来处理溢出。