五月综合激情婷婷六月,日韩欧美国产一区不卡,他扒开我内裤强吻我下面视频 ,无套内射无矿码免费看黄,天天躁,日日躁,狠狠躁

新聞動(dòng)態(tài)

python中opencv實(shí)現(xiàn)文字分割的實(shí)踐

發(fā)布日期:2022-03-21 18:08 | 文章來源:站長(zhǎng)之家

圖片文字分割的時(shí)候,常用的方法有兩種。一種是投影法,適用于排版工整,字間距行間距比較寬裕的圖像;還有一種是用OpenCV的輪廓檢測(cè),適用于文字不規(guī)則排列的圖像。

投影法

對(duì)文字圖片作橫向和縱向投影,即通過統(tǒng)計(jì)出每一行像素個(gè)數(shù),和每一列像素個(gè)數(shù),來分割文字。
分別在水平和垂直方向?qū)︻A(yù)處理(二值化)的圖像某一種像素進(jìn)行統(tǒng)計(jì),對(duì)于二值化圖像非黑即白,我們通過對(duì)其中的白點(diǎn)或者黑點(diǎn)進(jìn)行統(tǒng)計(jì),根據(jù)統(tǒng)計(jì)結(jié)果就可以判斷出每一行的上下邊界以及每一列的左右邊界,從而實(shí)現(xiàn)分割的目的。

算法步驟:

  • 使用水平投影和垂直投影的方式進(jìn)行圖像分割,根據(jù)投影的區(qū)域大小尺寸分割每行和每塊的區(qū)域,對(duì)原始圖像進(jìn)行二值化處理。
  • 投影之前進(jìn)行圖像灰度學(xué)調(diào)整做膨脹操作
  • 分別進(jìn)行水平投影和垂直投影
  • 根據(jù)投影的長(zhǎng)度和高度求取完整行和塊信息

橫板文字-小票文字分割

#小票水平分割
import cv2
import numpy as np
img = cv2.imread(r"C:\Users\An\Pictures\1.jpg")
cv2.imshow("Orig Image", img)
# 輸出圖像尺寸和通道信息
sp = img.shape
print("圖像信息:", sp)
sz1 = sp[0]  # height(rows) of image
sz2 = sp[1]  # width(columns) of image
sz3 = sp[2]  # the pixels value is made up of three primary colors
print('width: %d \n height: %d \n number: %d' % (sz2, sz1, sz3))
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
retval, threshold_img = cv2.threshold(gray_img, 120, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("threshold_img", threshold_img)
# 水平投影分割圖像
gray_value_x = []
for i in range(sz1):
 white_value = 0
 for j in range(sz2):
  if threshold_img[i, j] == 255:
white_value += 1
 gray_value_x.append(white_value)
print("", gray_value_x)
# 創(chuàng)建圖像顯示水平投影分割圖像結(jié)果
hori_projection_img = np.zeros((sp[0], sp[1], 1), np.uint8)
for i in range(sz1):
 for j in range(gray_value_x[i]):
  hori_projection_img[i, j] = 255
cv2.imshow("hori_projection_img", hori_projection_img)
text_rect = []
# 根據(jù)水平投影分割識(shí)別行
inline_x = 0
start_x = 0
text_rect_x = []
for i in range(len(gray_value_x)):
 if inline_x == 0 and gray_value_x[i] > 10:
  inline_x = 1
  start_x = i
 elif inline_x == 1 and gray_value_x[i] < 10 and (i - start_x) > 5:
  inline_x = 0
  if i - start_x > 10:
rect = [start_x - 1, i + 1]
text_rect_x.append(rect)
print("分行區(qū)域,每行數(shù)據(jù)起始位置Y:", text_rect_x)
# 每行數(shù)據(jù)分段
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 3))
dilate_img = cv2.dilate(threshold_img, kernel)
cv2.imshow("dilate_img", dilate_img)
for rect in text_rect_x:
 cropImg = dilate_img[rect[0]:rect[1],0:sp[1]]  # 裁剪圖像y-start:y-end,x-start:x-end
 sp_y = cropImg.shape
 # 垂直投影分割圖像
 gray_value_y = []
 for i in range(sp_y[1]):
  white_value = 0
  for j in range(sp_y[0]):
if cropImg[j, i] == 255:
 white_value += 1
  gray_value_y.append(white_value)
 # 創(chuàng)建圖像顯示水平投影分割圖像結(jié)果
 veri_projection_img = np.zeros((sp_y[0], sp_y[1], 1), np.uint8)
 for i in range(sp_y[1]):
  for j in range(gray_value_y[i]):
veri_projection_img[j, i] = 255
 cv2.imshow("veri_projection_img", veri_projection_img)
 # 根據(jù)垂直投影分割識(shí)別行
 inline_y = 0
 start_y = 0
 text_rect_y = []
 for i in range(len(gray_value_y)):
  if inline_y == 0 and gray_value_y[i] > 2:
inline_y = 1
start_y = i
  elif inline_y == 1 and gray_value_y[i] < 2 and (i - start_y) > 5:
inline_y = 0
if i - start_y > 10:
 rect_y = [start_y - 1, i + 1]
 text_rect_y.append(rect_y)
 text_rect.append([rect[0], rect[1], start_y - 1, i + 1])
 cropImg_rect = threshold_img[rect[0]:rect[1], start_y - 1:i + 1]  # 裁剪圖像
 cv2.imshow("cropImg_rect", cropImg_rect)
 # cv2.imwrite("C:/Users/ThinkPad/Desktop/cropImg_rect.jpg",cropImg_rect)
 # break
  # break
# 在原圖上繪制截圖矩形區(qū)域
print("截取矩形區(qū)域(y-start:y-end,x-start:x-end):", text_rect)
rectangle_img = cv2.rectangle(img, (text_rect[0][2], text_rect[0][0]), (text_rect[0][3], text_rect[0][1]),
  (255, 0, 0), thickness=1)
for rect_roi in text_rect:
 rectangle_img = cv2.rectangle(img, (rect_roi[2], rect_roi[0]), (rect_roi[3], rect_roi[1]), (255, 0, 0), thickness=1)
cv2.imshow("Rectangle Image", rectangle_img)
key = cv2.waitKey(0)
if key == 27:
 print(key)
 cv2.destroyAllWindows()

小票圖像二值化結(jié)果如下:

小票圖像結(jié)果分割如下:

豎版-古文文字分割

對(duì)于古籍來說,古籍文字書寫在習(xí)慣是從上到下的,所以說在掃描的時(shí)候應(yīng)該掃描列投影,在掃描行投影。

1.原始圖像進(jìn)行二值化

使用水平投影和垂直投影的方式進(jìn)行圖像分割,根據(jù)投影的區(qū)域大小尺寸分割每行和每塊的區(qū)域,對(duì)原始圖像進(jìn)行二值化處理。

原始圖像:


二值化后的圖像:

2.圖像膨脹

投影之前進(jìn)行圖像灰度學(xué)調(diào)整做膨脹操作,選取適當(dāng)?shù)暮耍瑢?duì)圖像進(jìn)行膨脹處理。

3.垂直投影

定位該行文字區(qū)域:
數(shù)值不為0的區(qū)域就是文字存在的地方(即二值化后白色部分的區(qū)域),為0的區(qū)域就是每行之間相隔的距離。
1、如果前一個(gè)數(shù)為0,則記錄第一個(gè)不為0的坐標(biāo)。
2、如果前一個(gè)數(shù)不為0,則記錄第一個(gè)為0的坐標(biāo)。形象的說就是從出現(xiàn)第一個(gè)非空白列到出現(xiàn)第一個(gè)空白列這段區(qū)域就是文字存在的區(qū)域。
通過以上規(guī)則就可以找出每一列文字的起始點(diǎn)和終止點(diǎn),從而確定每一列的位置信息。

垂直投影結(jié)果:


通過上面的垂直投影,根據(jù)其白色小山峰的起始位置就可以界定出每一列的起始位置,從而把每一列分割出來。

4.水平投影

根據(jù)投影的長(zhǎng)度和高度求取完整行和塊信息
通過水平投影可以獲得每一個(gè)字符左右的起始位置,這樣也就可以獲得到每一個(gè)字符的具體坐標(biāo)位置,即一個(gè)矩形框的位置。

import cv2
import numpy as np
import os
img = cv2.imread(r"C:\Users\An\Pictures\3.jpg")
save_path=r"E:\crop_img\result" #圖像分解的每一步保存的地址
crop_path=r"E:\crop_img\img" #圖像切割保存的地址
cv2.imshow("Orig Image", img)
# 輸出圖像尺寸和通道信息
sp = img.shape
print("圖像信息:", sp)
sz1 = sp[0]  # height(rows) of image
sz2 = sp[1]  # width(columns) of image
sz3 = sp[2]  # the pixels value is made up of three primary colors
print('width: %d \n height: %d \n number: %d' % (sz2, sz1, sz3))
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
retval, threshold_img = cv2.threshold(gray_img, 120, 255, cv2.THRESH_BINARY_INV)
cv2.imshow("threshold_img", threshold_img)
cv2.imwrite(os.path.join(save_path,"threshold_img.jpg"),threshold_img)
# 垂直投影分割圖像
gray_value_y = []
for i in range(sz2):
 white_value = 0
 for j in range(sz1):
  if threshold_img[j, i] == 255:
white_value += 1
 gray_value_y.append(white_value)
print("", gray_value_y)
#創(chuàng)建圖像顯示垂直投影分割圖像結(jié)果
veri_projection_img = np.zeros((sp[0], sp[1], 1), np.uint8)
for i in range(sz2):
 for j in range(gray_value_y[i]):
  veri_projection_img[j, i] = 255
cv2.imshow("veri_projection_img", veri_projection_img)
cv2.imwrite(os.path.join(save_path,"veri_projection_img.jpg"),veri_projection_img)
text_rect = []

# 根據(jù)垂直投影分割識(shí)別列
inline_y = 0
start_y = 0
text_rect_y = []
for i in range(len(gray_value_y)):
 if inline_y == 0 and gray_value_y[i]> 30:
  inline_y = 1
  start_y = i
 elif inline_y == 1 and gray_value_y[i] < 30 and (i - start_y) > 5:
  inline_y = 0
  if i - start_y > 10:
rect = [start_y - 1, i + 1]
text_rect_y.append(rect)
print("分列區(qū)域,每列數(shù)據(jù)起始位置Y:", text_rect_y)
# 每列數(shù)據(jù)分段
# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 3))
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dilate_img = cv2.dilate(threshold_img, kernel)
cv2.imshow("dilate_img", dilate_img)
cv2.imwrite(os.path.join(save_path,"dilate_img.jpg"),dilate_img)
for rect in text_rect_y:
 cropImg = dilate_img[0:sp[0],rect[0]:rect[1]]  # 裁剪圖像y-start:y-end,x-start:x-end
 sp_x = cropImg.shape
 # 垂直投影分割圖像
 gray_value_x = []
 for i in range(sp_x[0]):
  white_value = 0
  for j in range(sp_x[1]):
if cropImg[i, j] == 255:
 white_value += 1
  gray_value_x.append(white_value)
 # 創(chuàng)建圖像顯示水平投影分割圖像結(jié)果
 hori_projection_img = np.zeros((sp_x[0], sp_x[1], 1), np.uint8)
 for i in range(sp_x[0]):
  for j in range(gray_value_x[i]):
veri_projection_img[i, j] = 255
 # cv2.imshow("hori_projection_img", hori_projection_img)
 # 根據(jù)水平投影分割識(shí)別行
 inline_x = 0
 start_x = 0
 text_rect_x = []
 ind=0
 for i in range(len(gray_value_x)):
  ind+=1
  if inline_x == 0 and gray_value_x[i] > 2:
inline_x = 1
start_x = i
  elif inline_x == 1 and gray_value_x[i] < 2 and (i - start_x) > 5:
inline_x = 0
if i - start_x > 10:
 rect_x = [start_x - 1, i + 1]
 text_rect_x.append(rect_x)
 text_rect.append([start_x - 1, i + 1,rect[0], rect[1]])
 cropImg_rect = threshold_img[start_x - 1:i + 1,rect[0]:rect[1]]  # 裁剪二值化圖像
 crop_img=img[start_x - 1:i + 1,rect[0]:rect[1]] #裁剪原圖像
 # cv2.imshow("cropImg_rect", cropImg_rect)
 # cv2.imwrite(os.path.join(crop_path,str(ind)+".jpg"),crop_img)
 # break
  # break
# 在原圖上繪制截圖矩形區(qū)域
print("截取矩形區(qū)域(y-start:y-end,x-start:x-end):", text_rect)
rectangle_img = cv2.rectangle(img, (text_rect[0][2], text_rect[0][0]), (text_rect[0][3], text_rect[0][1]),
  (255, 0, 0), thickness=1)
for rect_roi in text_rect:
 rectangle_img = cv2.rectangle(img, (rect_roi[2], rect_roi[0]), (rect_roi[3], rect_roi[1]), (255, 0, 0), thickness=1)
cv2.imshow("Rectangle Image", rectangle_img)
cv2.imwrite(os.path.join(save_path,"rectangle_img.jpg"),rectangle_img)
key = cv2.waitKey(0)
if key == 27:
 print(key)
 cv2.destroyAllWindows()

分割結(jié)果如下:

從分割的結(jié)果上看,基本上實(shí)現(xiàn)了圖片中文字的分割。但由于中文結(jié)構(gòu)復(fù)雜性,對(duì)于一些文字的分割并不理想,字會(huì)出現(xiàn)過度分割、有粘連的兩個(gè)字會(huì)出現(xiàn)分割不夠的現(xiàn)象。可以從圖像預(yù)處理(圖像腐蝕膨脹),邊界判斷閾值的調(diào)整等方面進(jìn)行優(yōu)化。

到此這篇關(guān)于python中opencv實(shí)現(xiàn)文字分割的實(shí)踐的文章就介紹到這了,更多相關(guān)opencv 文字分割內(nèi)容請(qǐng)搜索本站以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持本站!

國外服務(wù)器租用

版權(quán)聲明:本站文章來源標(biāo)注為YINGSOO的內(nèi)容版權(quán)均為本站所有,歡迎引用、轉(zhuǎn)載,請(qǐng)保持原文完整并注明來源及原文鏈接。禁止復(fù)制或仿造本網(wǎng)站,禁止在非maisonbaluchon.cn所屬的服務(wù)器上建立鏡像,否則將依法追究法律責(zé)任。本站部分內(nèi)容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學(xué)習(xí)參考,不代表本站立場(chǎng),如有內(nèi)容涉嫌侵權(quán),請(qǐng)聯(lián)系alex-e#qq.com處理。

相關(guān)文章

實(shí)時(shí)開通

自選配置、實(shí)時(shí)開通

免備案

全球線路精選!

全天候客戶服務(wù)

7x24全年不間斷在線

專屬顧問服務(wù)

1對(duì)1客戶咨詢顧問

在線
客服

在線客服:7*24小時(shí)在線

客服
熱線

400-630-3752
7*24小時(shí)客服服務(wù)熱線

關(guān)注
微信

關(guān)注官方微信
頂部