我在Matlab中开发了一个脚本,用于分析彩色窃取的雕刻文本。我正在使用一系列形态学技术来提取文本并用OCR读取它。我需要在Raspberry Pi上实现它,因此我决定将我的Matlab代码转换为OpenCV(在python中)。我试图转移一些方法,它们的工作方式类似,但我如何实现imreconstruct和imbinarize(如下所示)到OpenCV? (这里的挑战是适当区分前景和背景)。
也许我应该尝试添加grabCut
或getStructuringElement
或morphologyEx
或dilate
?我尝试了各种组合但没有找到完美的解决方案。
如果有人能就如何大致改进OCR过程的提取和准确性给我提出建议,我会把整个脚本都放在两者上我会非常感激。
基于灰度图像的bin值。我更改了一些参数 那些功能:
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
kernel = numpy.ones((5,5),numpy.uint8)
blur = cv2.GaussianBlur(img,(5,5),0)
erosion = cv2.erode(blur,kernel,iterations = 1)
opening = cv2.morphologyEx(erosion, cv2.MORPH_OPEN, kernel)
#bremove = cv2.grabCut(opening,mask,rect,bgdModelmode==GC_INIT_WITH_MASK)
#th3 = cv2.adaptiveThreshold(opening,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU,11,2)
ret, thresh= cv2.threshold(opening,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
ocr = pytesseract.image_to_string(Image.open('image2.png'),config='stdout -c tessedit_char_whitelist=0123456789')
这是输入图像:
答案 0 :(得分:2)
我根据您的雕刻文本样本制定了代码以获得正面结果。
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输出:
如果您能用更多的样本图像反馈您的测试结果,那就太棒了。
答案 1 :(得分:1)
我很惊讶matlab和opencv之间有多大区别,当它们似乎都使用相同的算法时。你为什么两次运行imbinarize
?灵敏度关键字实际上做了什么(数学上,在背景之后)。因为他们显然只有几个步骤而不仅仅是裸OTSU。
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)
显示的图像是:
经过一番清理后:
所有这一切都不一样,当然不如matlab好。但基本原则似乎是一样的,只是数字需要玩。
更好的方法可能是通过图像的平均值来做阈值,然后使用其输出作为掩模来自适应阈值原始图像。希望结果会比opencv和matlab都好。
尝试使用ADAPTIVE_THRESH_MEAN_C,你可以得到一些非常好的结果,但周围有更多的垃圾。同样,也许如果你可以用它作为掩码来隔离文本然后再次进行阈值处理,那么它可能会变得更好。侵蚀和膨胀核的形状也会在这里产生很大的不同。
答案 2 :(得分:1)
我可以从您的代码中看到,您已经在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)
通过应用这些转换,我得到了更好的结果。
答案 3 :(得分:0)
尝试下面,它可以识别较轻的雕刻文本样本。希望它有所帮助。
def show(img):
plt.imshow(img, cmap="gray")
plt.show()
# load the input image
img = cv2.imread('./imagesStackoverflow/engraved_text2.jpg',0);
show(img)
# apply CLAHE to adjust the contrast
clahe = cv2.createCLAHE(clipLimit=5.1, tileGridSize=(5,3))
cl1 = clahe.apply(img)
img = cl1.copy()
show(img)
img = cv2.GaussianBlur(img,(3,3), 1)
ret, mask = cv2.threshold(img, 125, 150, cv2.THRESH_BINARY) # turn 125, 150 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:
# Page Segmentation mode (PSmode) = 11 (defualt = 3)
# OCR Enginer Mode (OEM) = 3 (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