實(shí)現(xiàn)步驟:
1、通過(guò)水平投影對(duì)圖形進(jìn)行水平分割,獲取每一行的圖像;
2、通過(guò)垂直投影對(duì)分割的每一行圖像進(jìn)行垂直分割,最終確定每一個(gè)字符的坐標(biāo)位置,分割出每一個(gè)字符;
先簡(jiǎn)單介紹一下投影法:分別在水平和垂直方向?qū)︻A(yù)處理(二值化)的圖像某一種像素進(jìn)行統(tǒng)計(jì),對(duì)于二值化圖像非黑即白,我們通過(guò)對(duì)其中的白點(diǎn)或者黑點(diǎn)進(jìn)行統(tǒng)計(jì),根據(jù)統(tǒng)計(jì)結(jié)果就可以判斷出每一行的上下邊界以及每一列的左右邊界,從而實(shí)現(xiàn)分割的目的。
下面通過(guò)Python+opencv來(lái)實(shí)現(xiàn)該功能
首先來(lái)實(shí)現(xiàn)水平投影:
import cv2 import numpy as np '''水平投影''' def getHProjection(image): hProjection = np.zeros(image.shape,np.uint8) #圖像高與寬 (h,w)=image.shape #長(zhǎng)度與圖像高度一致的數(shù)組 h_ = [0]*h #循環(huán)統(tǒng)計(jì)每一行白色像素的個(gè)數(shù) for y in range(h): for x in range(w): if image[y,x] == 255: h_[y]+=1 #繪制水平投影圖像 for y in range(h): for x in range(h_[y]): hProjection[y,x] = 255 cv2.imshow('hProjection2',hProjection) return h_ if __name__ == "__main__": #讀入原始圖像 origineImage = cv2.imread('test.jpg') # 圖像灰度化 #image = cv2.imread('test.jpg',0) image = cv2.cvtColor(origineImage,cv2.COLOR_BGR2GRAY) cv2.imshow('gray',image) # 將圖片二值化 retval, img = cv2.threshold(image,127,255,cv2.THRESH_BINARY_INV) cv2.imshow('binary',img) #水平投影 H = getHProjection(img)
通過(guò)上面的水平投影,根據(jù)其白色小山峰的起始位置就可以界定出每一行的起始位置,從而把每一行分割出來(lái)。
獲得每一行圖像之后,可以對(duì)其進(jìn)行垂直投影
def getVProjection(image): vProjection = np.zeros(image.shape,np.uint8); #圖像高與寬 (h,w) = image.shape #長(zhǎng)度與圖像寬度一致的數(shù)組 w_ = [0]*w #循環(huán)統(tǒng)計(jì)每一列白色像素的個(gè)數(shù) for x in range(w): for y in range(h): if image[y,x] == 255: w_[x]+=1 #繪制垂直平投影圖像 for x in range(w): for y in range(h-w_[x],h): vProjection[y,x] = 255 cv2.imshow('vProjection',vProjection) return w_
通過(guò)垂直投影可以獲得每一個(gè)字符左右的起始位置,這樣也就可以獲得到每一個(gè)字符的具體坐標(biāo)位置,即一個(gè)矩形框的位置。
下面是實(shí)現(xiàn)的全部代碼:
import cv2 import numpy as np '''水平投影''' def getHProjection(image): hProjection = np.zeros(image.shape,np.uint8) #圖像高與寬 (h,w)=image.shape #長(zhǎng)度與圖像高度一致的數(shù)組 h_ = [0]*h #循環(huán)統(tǒng)計(jì)每一行白色像素的個(gè)數(shù) for y in range(h): for x in range(w): if image[y,x] == 255: h_[y]+=1 #繪制水平投影圖像 for y in range(h): for x in range(h_[y]): hProjection[y,x] = 255 cv2.imshow('hProjection2',hProjection) return h_ def getVProjection(image): vProjection = np.zeros(image.shape,np.uint8); #圖像高與寬 (h,w) = image.shape #長(zhǎng)度與圖像寬度一致的數(shù)組 w_ = [0]*w #循環(huán)統(tǒng)計(jì)每一列白色像素的個(gè)數(shù) for x in range(w): for y in range(h): if image[y,x] == 255: w_[x]+=1 #繪制垂直平投影圖像 for x in range(w): for y in range(h-w_[x],h): vProjection[y,x] = 255 #cv2.imshow('vProjection',vProjection) return w_ if __name__ == "__main__": #讀入原始圖像 origineImage = cv2.imread('test.jpg') # 圖像灰度化 #image = cv2.imread('test.jpg',0) image = cv2.cvtColor(origineImage,cv2.COLOR_BGR2GRAY) cv2.imshow('gray',image) # 將圖片二值化 retval, img = cv2.threshold(image,127,255,cv2.THRESH_BINARY_INV) cv2.imshow('binary',img) #圖像高與寬 (h,w)=img.shape Position = [] #水平投影 H = getHProjection(img) start = 0 H_Start = [] H_End = [] #根據(jù)水平投影獲取垂直分割位置 for i in range(len(H)): if H[i] > 0 and start ==0: H_Start.append(i) start = 1 if H[i] <= 0 and start == 1: H_End.append(i) start = 0 #分割行,分割之后再進(jìn)行列分割并保存分割位置 for i in range(len(H_Start)): #獲取行圖像 cropImg = img[H_Start[i]:H_End[i], 0:w] #cv2.imshow('cropImg',cropImg) #對(duì)行圖像進(jìn)行垂直投影 W = getVProjection(cropImg) Wstart = 0 Wend = 0 W_Start = 0 W_End = 0 for j in range(len(W)): if W[j] > 0 and Wstart ==0: W_Start =j Wstart = 1 Wend=0 if W[j] <= 0 and Wstart == 1: W_End =j Wstart = 0 Wend=1 if Wend == 1: Position.append([W_Start,H_Start[i],W_End,H_End[i]]) Wend =0 #根據(jù)確定的位置分割字符 for m in range(len(Position)): cv2.rectangle(origineImage, (Position[m][0],Position[m][1]), (Position[m][2],Position[m][3]), (0 ,229 ,238), 1) cv2.imshow('image',origineImage) cv2.waitKey(0)
從分割的結(jié)果上看,基本上實(shí)現(xiàn)了圖片中文字的分割。但由于中文結(jié)構(gòu)復(fù)雜性,對(duì)于一些文字的分割并不理想,比如“葉”、“桃”等字會(huì)出現(xiàn)過(guò)度分割現(xiàn)象;對(duì)于有粘連的兩個(gè)字會(huì)出現(xiàn)分割不夠的現(xiàn)象,比如上圖中的“念想”。不過(guò)可以從圖像預(yù)處理(腐蝕),邊界判斷閾值的調(diào)整等方面進(jìn)行優(yōu)化。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
