如何在OpenCV中实现imbinalize

2024-10-01 07:27:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Matlab中开发了一个脚本,它分析了一幅彩色画上的雕刻文本。我正在使用一系列的形态学技术来提取文本并用OCR阅读。我需要在Raspberry Pi上实现它,因此我决定将我的Matlab代码转换成OpenCV(python语言)。我试着转移一些方法,它们的工作原理是相似的,但是我如何实现imreconstruct和imbinalize(如下所示)到OpenCV?(这里的挑战是适当区分前景和背景)。在

也许我应该尝试添加grabCutgetStructuringElement或{}或{}?我尝试了各种组合,但没有找到完美的解决方案。在

我将把整个脚本两者如果有人能给我建议,一般如何提高这种提取和OCR过程的准确性,我将不胜感激。在

Based on bin values of grey-scale image. I change some parameters in those functions:

Matlab:

se = strel('disk', 300);
img = imtophat(img, se);
maker = imerode(img, strel('line',100,0)); %for whiter ones
maker = imerode(img, strel('line',85,0)); %for medium
maker = imerode(img, strel('line',5,0));

imgClear = imreconstruct(maker, img);

imgBlur = imgaussfilt(imgClear,1); %less blur for whiter frames

BW = imbinarize(imgBlur,'adaptive','ForegroundPolarity','Bright',...
    'Sensitivity',0.7);   %process for medium

BW = imbinarize(imgBlur, 'adaptive', 'ForegroundPolarity',...
        'Dark', 'Sensitivity', 0.4); % process for black and white

res = ocr(BW, 'CharacterSet', '0123456789', 'TextLayout', 'Block');
res.Text;

OpenCv

^{pr2}$

以下是输入图像:

enter image description here

Matlab outcome (result 573702)

OpenCV outcome (result 573102

Light colour image

Matlab process full detection rate


Tags: 文本脚本imgforlineopencvocrbw
3条回答

当matlab和opencv似乎都使用相同的算法时,它们之间的差别有多大,我感到惊讶。为什么要运行imbinarize两次?sensitivity关键字的实际作用是什么(从数学上讲,在后台)。因为它们显然比光秃秃的大冢还要多出好几步。在

import cv2
import numpy as np
import matplotlib.pyplot as plt

def show(img):
    plt.imshow(img, cmap="gray")
    plt.show()

img = cv2.imread("letters.jpg", cv2.IMREAD_GRAYSCALE)

kernel = np.ones((3,3), np.uint8)

blur = cv2.GaussianBlur(img,(3,3), 0)
erosion = cv2.erode(blur, kernel, iterations=3)
opening = cv2.dilate(erosion, kernel)

th3 = cv2.adaptiveThreshold(opening, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
            cv2.THRESH_BINARY, 45, 2)
show(th3)

kernel2 = cv2.getGaussianKernel(6, 2) #np.ones((6,6))
kernel2 = np.outer(kernel2, kernel2)
th3 = cv2.dilate(th3, kernel2)
th3 = cv2.erode(th3, kernel)
show(th3)

显示的图像包括:

First image, the immediate result of thresholding

经过一番清理:

A bit more cleaned up and lean. Not really as nice as matlab output.

所以总的来说不一样,当然也没有matlab好。但基本原理似乎是一样的,只是数字需要玩玩。在

一个更好的方法可能是用图像的平均值来做一个阈值,然后用它的输出作为掩模来自适应阈值化原始图像。希望结果会比opencv和matlab都好。在

试着用自适应的THRESH做这个,你可以得到一些非常好的结果,但是周围有更多的垃圾。同样,如果你可以用它作为一个遮罩来隔离文本,然后再做一次tresholding,它可能会更好。同时,侵蚀和膨胀的核的形状也会造成很大的不同。在

我能从你的代码中看到的是你在Matlab代码中使用了tophat过滤作为第一步。但是,我在python OpenCV代码中看不到相同的情况。 Python内置了tophat过滤器,尝试应用它来获得类似的结果

kernel = np.ones((5,5),np.uint8) tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)

另外,试着用CLAHE,它能给你的图像提供更好的对比度,然后用blackhat过滤掉小细节。在

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) cl1 = clahe.apply(img) 通过应用这些转换,我得到了更好的结果。在

我根据你雕刻的文本样本计算出了一个肯定的结果。在

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

def show(img):
    plt.imshow(img, cmap="gray")
    plt.show()

# load the input image
img = cv2.imread('./imagesStackoverflow/engraved_text.jpg',0);
show(img)

ret, mask = cv2.threshold(img, 60, 120, cv2.THRESH_BINARY)  # turn 60, 120 for the best OCR results
kernel = np.ones((5,3),np.uint8)
mask = cv2.erode(mask,kernel,iterations = 1)
show(mask)

# I used a version of OpenCV with Tesseract, you may use your pytesseract and set the modes as:
#   OCR Enginer Mode (OEM) = 3 (defualt = 3)
#   Page Segmentation mode (PSmode) = 11 (defualt = 3)
tesser = cv2.text.OCRTesseract_create('C:/Program Files/Tesseract 4.0.0/tessdata/','eng','0123456789',11,3)
retval = tesser.run(mask, 0) # return string type

print 'OCR:' + retval

处理后的图像和OCR输出:

enter image description here

如果你能用更多的样本图像反馈你的测试结果,那就太好了。在

相关问题 更多 >