如何使用OpenCV自動校正文本圖像
點擊上方“小白學(xué)視覺”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
今天,我們想與您分享解決圖像偏移校正問題(拉直旋轉(zhuǎn)圖像)的簡單解決方案。如果我們正在從歪斜圖像中提取文本的內(nèi)容,則必須以一種或另一種形式處理圖像。從攝像機圖片到掃描的文檔-將清理后的圖像饋送到OCR工具之前,去歪斜是圖像預(yù)處理中的必要步驟。
讓我們開始討論Deskeweing算法的一般概念。我們的主要目標是將旋轉(zhuǎn)的圖像分成文本塊,并確定它們的角度。為了讓您詳細了解我將使用的方法:
1. 照常-將圖像轉(zhuǎn)換為灰度。
2. 應(yīng)用輕微的模糊以減少圖像中的噪點。
3. 現(xiàn)在,我們的目標是找到帶有文本的區(qū)域,即圖像的文本塊。為了使文本塊檢測更容易,我們將反轉(zhuǎn)并最大化圖像的顏色,這將通過閾值化來實現(xiàn)。因此,現(xiàn)在文本變?yōu)榘咨ㄇ『脼?55,255,255白色),而背景為黑色(同樣為0,0,0黑色)。
4. 要查找文本塊,我們需要合并該塊的所有打印字符。我們通過膨脹(擴展白色像素)來實現(xiàn)。在X軸上使用較大的內(nèi)核可以消除單詞之間的所有空間,而在Y軸上使用較小的內(nèi)核可以將彼此之間的一個塊的行混合在一起,但保持文本塊之間的較大間隔不變。
5. 現(xiàn)在,用最小面積矩形包圍輪廓的簡單輪廓檢測將形成我們需要的所有文本塊。
6. 確定傾斜角度的方法有很多種,但我們將堅持簡單的方法-使用最大的文本塊并使用其角度。
現(xiàn)在切換到python代碼:
# Calculate skew angle of an imagedef getSkewAngle(cvImage) -> float:#Prep image, copy, convert to gray scale, blur, and thresholdnewImage = cvImage.copy()gray = cv2.cvtColor(newImage, cv2.COLOR_BGR2GRAY)blur = cv2.GaussianBlur(gray, (9, 9), 0)thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV +cv2.THRESH_OTSU)[1]#Apply dilate to merge text into meaningful lines/paragraphs.#Use larger kernel on X axis to merge characters into single line, cancellingout any spaces.#But use smaller kernel on Y axis to separate between different blocks of textkernel = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 5))dilate = cv2.dilate(thresh, kernel, iterations=5)#Find all contourshierarchy = cv2.findContours(dilate, cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)contours = sorted(contours, key = cv2.contourArea, reverse = True)#Find largest contour and surround in min area boxlargestContour = contours[0]minAreaRect= cv2.minAreaRect(largestContour)#Determine the angle. Convert it to the value that was originally used to obtainskewed imageangle = minAreaRect[-1]if angle < -45:angle = 90 + anglereturn -1.0 * angle
獲得偏斜角后,我們只需要重新旋轉(zhuǎn)圖像即可:
# Rotate the image around its centerdef rotateImage(cvImage, angle: float):newImage = cvImage.copy()w) = newImage.shape[:2]center = (w // 2, h // 2)M= cv2.getRotationMatrix2D(center, angle, 1.0)newImage = cv2.warpAffine(newImage, M, (w, h), flags=cv2.INTER_CUBIC,borderMode=cv2.BORDER_REPLICATE)return newImage# Deskew imagedef deskew(cvImage):angle = getSkewAngle(cvImage)return rotateImage(cvImage, -1.0 * angle)



可視化步驟
其他案例可能需要更多的計算,而不僅僅是采取最大的方法,并且可以開始嘗試一些其他策略。
1- 可以使用所有文本塊的平均角度:
allContourAngles = [cv2.minAreaRect(c)[-1]for c in contours]angle = sum(allContourAngles) /len(allContourAngles)
2- 可以采用中間塊的角度:
middleContour = contours[len(contours) //2]angle = cv2.minAreaRect(middleContour)[-1]
3- 可以嘗試最大,最小和中間塊的平均角度。
largestContour = contours[0]middleContour = contours[len(contours) //2]smallestContour = contours[-1]angle =sum([cv2.minAreaRect(largestContour)[-1], cv2.minAreaRect(middleContour)[-1],cv2.minAreaRect(smallestContour)[-1]]) / 3
那只是我們可以立即想到的一些替代方式。繼續(xù)嘗試,找出最適合您的情況的方法!
為了測試這種方法,我使用了一個新生成的帶有Lorem Ipsum文本的PDF文件。本文檔的首頁以300 DPI分辨率(使用PDF文檔時最常用的設(shè)置)呈現(xiàn)。之后,通過拍攝原始圖像并在-10度到+10度范圍內(nèi)隨機旋轉(zhuǎn)來生成20個樣本圖像的測試數(shù)據(jù)集。然后,我將圖像及其傾斜角度保存在一起。您可以在我的GitHub存儲庫中找到用于生成這些示例圖像的所有代碼,這里不再贅述。
測試結(jié)果的統(tǒng)計樣本:
Item #0,with angle=1.77, calculated=1.77, difference=0.0%Item #1,with angle=-1.2, calculated=-1.19, difference=0.83%Item #2,with angle=8.92, calculated=8.92, difference=0.0%Item #3,with angle=8.68, calculated=8.68, difference=0.0%Item #4,with angle=4.83, calculated=4.82, difference=0.21%Item #5,with angle=4.41, calculated=4.4, difference=0.23%Item #6,with angle=-5.93, calculated=-5.91, difference=0.34%Item #7,with angle=-3.32, calculated=-3.33, difference=0.3%Item #8,with angle=6.53, calculated=6.54, difference=0.15%Item #9,with angle=-2.66, calculated=-2.65, difference=0.38%Item #10,with angle=-2.2, calculated=-2.19, difference=0.45%Item #11,with angle=-1.42, calculated=-1.4, difference=1.41%Item #12,with angle=-6.77, calculated=-6.77, difference=0.0%Item #13,with angle=-9.26, calculated=-9.25, difference=0.11%Item #14,with angle=4.36, calculated=4.35, difference=0.23%Item #15,with angle=5.49, calculated=5.48, difference=0.18%Item #16,with angle=-4.54, calculated=-4.55, difference=0.22%Item #17,with angle=-2.54, calculated=-2.54, difference=0.0%Item #18,with angle=4.65, calculated=4.66, difference=0.22%Item #19,with angle=-4.33, calculated=-4.32, difference=0.23%MinError: 0.0%MaxError: 1.41%Avg Error: 0.27%
這種方法效果很好,與真實的歪斜角度僅產(chǎn)生很小的偏差。對于人眼和OCR引擎而言,此類錯誤已不再明顯。
交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~

