【发布时间】:2020-10-29 05:37:45
【问题描述】:
【问题讨论】:
标签: python opencv image-processing information-retrieval opencv-python
【问题讨论】:
标签: python opencv image-processing information-retrieval opencv-python
这是我们可以解决问题的一种方法,
import cv2
import numpy as np
image=cv2.imread('path/to/image.jpg')
### binarising image
gray_scale=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
th1,img_bin = cv2.threshold(gray_scale,150,225,cv2.THRESH_BINARY)
定义垂直和水平内核
lineWidth = 7
lineMinWidth = 55
kernal1 = np.ones((lineWidth,lineWidth), np.uint8)
kernal1h = np.ones((1,lineWidth), np.uint8)
kernal1v = np.ones((lineWidth,1), np.uint8)
kernal6 = np.ones((lineMinWidth,lineMinWidth), np.uint8)
kernal6h = np.ones((1,lineMinWidth), np.uint8)
kernal6v = np.ones((lineMinWidth,1), np.uint8)
检测水平线
img_bin_h = cv2.morphologyEx(~img_bin, cv2.MORPH_CLOSE, kernal1h) # bridge small gap in horizonntal lines
img_bin_h = cv2.morphologyEx(img_bin_h, cv2.MORPH_OPEN, kernal6h) # kep ony horiz lines by eroding everything else in hor direction
寻找垂直线
## detect vert lines
img_bin_v = cv2.morphologyEx(~img_bin, cv2.MORPH_CLOSE, kernal1v) # bridge small gap in vert lines
img_bin_v = cv2.morphologyEx(img_bin_v, cv2.MORPH_OPEN, kernal6v)# kep ony vert lines by eroding everything else in vert direction
合并垂直和水平线以获得块。添加膨胀层以消除小间隙
### function to fix image as binary
def fix(img):
img[img>127]=255
img[img<127]=0
return img
img_bin_final = fix(fix(img_bin_h)|fix(img_bin_v))
finalKernel = np.ones((5,5), np.uint8)
img_bin_final=cv2.dilate(img_bin_final,finalKernel,iterations=1)
对二进制图像应用连通分量分析以获得所需的块。
ret, labels, stats,centroids = cv2.connectedComponentsWithStats(~img_bin_final, connectivity=8, ltype=cv2.CV_32S)
### skipping first two stats as background
for x,y,w,h,area in stats[2:]:
cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),2)
【讨论】:
你也可以使用contours来解决这个问题。
# Reading the image in grayscale and thresholding it
Image = cv2.imread("findBox.jpg", 0)
ret, Thresh = cv2.threshold(Image, 100, 255, cv2.THRESH_BINARY)
现在执行两次膨胀和腐蚀以连接框内的虚线。
kernel = np.ones((3, 3), dtype=np.uint8)
Thresh = cv2.dilate(Thresh, kernel, iterations=2)
Thresh = cv2.erode(Thresh, kernel, iterations=2)
在带有 cv2.RETR_TREE 标志的图像中查找轮廓以获取所有具有父子关系的轮廓。 For more info on this.
Contours, Hierarchy = cv2.findContours(Thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
现在检测到图像中的所有框以及所有字母。我们必须消除检测到的字母、非常小的轮廓(由于噪声),以及那些内部包含较小框的框。
为此,我正在运行一个 for 循环迭代检测到的所有轮廓,并使用此循环将每个轮廓的 3 个值保存在 3 个不同的列表中。
Areas = []
Rects = []
Ratios = []
for Contour in Contours:
# Getting bounding rectangle
Rect = cv2.boundingRect(Contour)
# Drawing contour on new image and finding number of white pixels for contour area
C_Image = np.zeros(Thresh.shape, dtype=np.uint8)
cv2.drawContours(C_Image, [Contour], -1, 255, -1)
ContourArea = np.sum(C_Image == 255)
# Area of the bounding rectangle
Rect_Area = Rect[2]*Rect[3]
# Calculating ratio as explained above
Ratio = ContourArea / Rect_Area
# Storing data
Areas.append(ContourArea)
Rects.append(Rect)
Ratios.append(Ratio)
BoxesIndices = [i for i in range(len(Contours)) if Ratios[i] >= 0.99 and Areas[i] > 3600]
FinalBoxes = [Rects[i] for i in BoxesIndices if Hierarchy[0][i][2] == -1 or BoxesIndices.count(Hierarchy[0][i][2]) == 0]
【讨论】: