簡體   English   中英

如何在OpenCV中實現Imbinarize

[英]How to implement imbinarize in OpenCV

我在Matlab中開發了腳本,該腳本正在分析顏色竊取上的雕刻文字。 我正在使用多種形態學技術來提取文本並使用OCR進行閱讀。 我需要在Raspberry Pi上實現它,因此我決定將Matlab代碼傳輸到OpenCV(在python中)。 我嘗試轉移一些方法,它們的工作方式相似,但是如何將imreconstruct和imbinarize(如下所示)實現到OpenCV? (這里的挑戰是適當區分前景和背景)。

也許我應該嘗試添加grabCutgetStructuringElementmorphologyEx還是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')

這是輸入圖像:

在此處輸入圖片說明

Matlab結果(結果573702)

OpenCV結果(結果573102

淺色圖像

Matlab程序全檢率

我根據您雕刻的文字樣本得出了代碼,得到了肯定的結果。

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輸出:

在此處輸入圖片說明

如果您可以提供更多示例圖像來反饋測試結果,那就太好了。

當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輸出好。

所以總的來說不一樣,當然不如matlab好。 但是基本原理似乎相同,只是數字需要使用。

更好的方法可能是通過圖像的平均值進行閾值處理,然后將其輸出用作掩碼以對原始圖像進行自適應閾值處理。 希望那時的結果會比opencv和matlab都好。

嘗試使用ADAPTIVE_THRESH_MEAN_C進行操作,您可以獲得一些非常不錯的結果,但周圍還有更多的垃圾。 同樣,也許如果您可以將其用作遮罩來隔離文本,然后再次進行輸入,則可能會更好。 侵蝕和膨脹核的形狀也會在這里產生很大的變化。

從您的代碼中可以看到,第一步是您在Matlab代碼中使用了高帽過濾。 但是,在您的python OpenCV代碼中看不到相同的內容。 Python內置了tophat過濾器,嘗試應用該過濾器以獲得相似的結果

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

另外,嘗試使用CLAHE,它可以使您的圖像對比度更好,然后應用黑帽過濾掉小的細節。

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8)) cl1 = clahe.apply(img)通過應用這些轉換,我得到了更好的結果。

經過以下嘗試,它可以識別較淺的雕刻文字樣本。 希望能幫助到你。

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

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM