def get_contours(image, polydb=0.03, contour_range=5, show=False):
# find the contours in the edged image, keeping only the largest ones, and initialize the screen contour
if cv2version == 3: im2, contours, hierarchy = cv2.findContours(image.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(contours, key = cv2.contourArea, reverse = True)[:contour_range]
# loop over the contours
screenCnt = None
for c in cnts:
# approximate the contour
peri = cv2.arcLength(c, True) #finds the Contour Perimeter
approx = cv2.approxPolyDP(c, polydb * peri, True)
# if our approximated contour has four points, then we can assume that we have found our screen
if len(approx) == 4:
screenCnt = approx
break
if screenCnt is None: raise EdgeNotFound()
# sometimes the algorythm finds a strange non-convex shape. The shape conforms to the card but its not complete, so then just complete the shape into a convex form
if not cv2.isContourConvex(screenCnt):
screenCnt = cv2.convexHull(screenCnt)
x,y,w,h = cv2.boundingRect(screenCnt)
screenCnt = np.array([[[x, y]], [[x+w, y]], [[x+w, y+h]], [[x, y+h]]])
if show: #this is for debugging puposes
new_image = image.copy()
cv2.drawContours(new_image, [screenCnt], -1, (255, 255, 0), 2)
cv2.imshow("Contour1 image", new_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
return screenCnt
python类arcLength()的实例源码
def get_contours(image, polydb=0.1, contour_range=7, show=False):
# find the contours in the edged image, keeping only the largest ones, and initialize the screen contour
contours = _findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(contours, key = cv2.contourArea, reverse = True)[:contour_range]
# loop over the contours
screenCnt = None
for c in cnts:
# approximate the contour
peri = cv2.arcLength(c, True) #finds the Contour Perimeter
approx = cv2.approxPolyDP(c, polydb * peri, True)
# if our approximated contour has four points, then we can assume that we have found our screen
if len(approx) == 4:
screenCnt = approx
break
if screenCnt is None:
raise EdgeNotFound()
# sometimes the algorythm finds a strange non-convex shape. The shape conforms to the card but its not complete, so then just complete the shape into a convex form
if not cv2.isContourConvex(screenCnt):
screenCnt = cv2.convexHull(screenCnt)
x,y,w,h = cv2.boundingRect(screenCnt)
screenCnt = numpy.array([[[x, y]], [[x+w, y]], [[x+w, y+h]], [[x, y+h]]])
if show: #this is for debugging puposes
new_image = image.copy()
cv2.drawContours(new_image, [screenCnt], -1, (255, 255, 0), 2)
cv2.imshow("Contour1 image", new_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
return screenCnt
def get_contours(image, polydb=0.03, contour_range=7, show=False):
# find the contours in the edged image, keeping only the largest ones, and initialize the screen contour
# if cv2version == 3: im2, contours, hierarchy = cv2.findContours(image.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = _findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(contours, key = cv2.contourArea, reverse = True)[:contour_range]
# loop over the contours
screenCnt = None
for c in cnts:
# approximate the contour
peri = cv2.arcLength(c, True) #finds the Contour Perimeter
approx = cv2.approxPolyDP(c, polydb * peri, True)
# if our approximated contour has four points, then we can assume that we have found our screen
if len(approx) == 4:
screenCnt = approx
break
if screenCnt is None: raise EdgeNotFound()
# sometimes the algorythm finds a strange non-convex shape. The shape conforms to the card but its not complete, so then just complete the shape into a convex form
if not cv2.isContourConvex(screenCnt):
screenCnt = cv2.convexHull(screenCnt)
x,y,w,h = cv2.boundingRect(screenCnt)
screenCnt = numpy.array([[[x, y]], [[x+w, y]], [[x+w, y+h]], [[x, y+h]]])
if show: #this is for debugging puposes
new_image = image.copy()
cv2.drawContours(new_image, [screenCnt], -1, (255, 255, 0), 2)
cv2.imshow("Contour1 image", new_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
return screenCnt
def countVertices(contour):
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.04 * peri, True)
return len(approx)
#Classifies a contour as a generic polygon shape
def countVertices(contour):
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.04 * peri, True)
return len(approx)
#Classifies a contour as a generic polygon shape
digital_display_ocr.py 文件源码
项目:digital-display-character-rec
作者: upupnaway
项目源码
文件源码
阅读 27
收藏 0
点赞 0
评论 0
def find_display_contour(edge_img_arr):
display_contour = None
edge_copy = edge_img_arr.copy()
contours,hierarchy = cv2.findContours(edge_copy, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
top_cntrs = sorted(contours, key = cv2.contourArea, reverse = True)[:10]
for cntr in top_cntrs:
peri = cv2.arcLength(cntr,True)
approx = cv2.approxPolyDP(cntr, 0.02 * peri, True)
if len(approx) == 4:
display_contour = approx
break
return display_contour
def FindField(self):
#Feld: Hue zwischen 60 und 100
LowerGreen = np.array([40,0,0])
UpperGreen = np.array([90,255,150])
mask = cv2.inRange(self.ImgHSV,LowerGreen,UpperGreen)
# plt.figure()
# plt.imshow(mask,cmap='gray')
mask = self.SmoothFieldMask(mask)
# plt.figure()
# plt.imshow(mask.copy(),cmap='gray')
im2, contours, hierarchy = cv2.findContours(mask.copy(),cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
if(len(contours) <= 0):
return
contours_sorted = sorted(contours, key = cv2.contourArea, reverse=True)[:10]
peri = cv2.arcLength(contours_sorted[0],True)
approx = cv2.approxPolyDP(contours_sorted[0], 0.02*peri, True)
if(len(approx) >-1):#== 4):
self.FieldContours = approx
cv2.rectangle(mask,(((self.FieldContours[0])[0])[0],((self.FieldContours[0])[0])[1]),(((self.FieldContours[2])[0])[0],((self.FieldContours[2])[0])[1]),(128,128,128),3)
# plt.imshow(mask, cmap="gray")
# plt.show()
def detect_cnt_again(poly, base_img):
"""
???????????????????
:param poly: ndarray
:param base_img: ndarray
:return: ndarray
"""
# ?????????????????flag
flag = False
# ?????????????????????????
top_left, bottom_left, top_right, bottom_right = get_corner_node_list(poly)
roi_img = get_roi_img(base_img, bottom_left, bottom_right, top_left, top_right)
img = get_init_process_img(roi_img)
# ?????????
cnt = get_max_area_cnt(img)
# ?????????????????????
if cv2.contourArea(cnt) > roi_img.shape[0] * roi_img.shape[1] * SHEET_AREA_MIN_RATIO:
flag = True
poly = cv2.approxPolyDP(cnt, cv2.arcLength((cnt,), True) * 0.1, True)
top_left, bottom_left, top_right, bottom_right = get_corner_node_list(poly)
if not poly.shape[0] == 4:
raise PolyNodeCountError
# ?????????????????
base_poly_nodes = np.float32([top_left[0], bottom_left[0], top_right[0], bottom_right[0]])
base_nodes = np.float32([[0, 0],
[base_img.shape[1], 0],
[0, base_img.shape[0]],
[base_img.shape[1], base_img.shape[0]]])
transmtx = cv2.getPerspectiveTransform(base_poly_nodes, base_nodes)
if flag:
img_warp = cv2.warpPerspective(roi_img, transmtx, (base_img.shape[1], base_img.shape[0]))
else:
img_warp = cv2.warpPerspective(base_img, transmtx, (base_img.shape[1], base_img.shape[0]))
return img_warp
def info(self):
s = []
s.append('Located %d squares within image')
s.append('Each square is a contour from cv2.findContours')
i = 0
for sq in self.squares:
i += 1
s.append('Square %d : length = %d : area = %d' % (sq.ID, cv2.arcLength(sq.contour, True), sq.area))
return '\n'.join(s)
def info(self):
s = []
s.append('Located %d squares within image')
s.append('Each square is a contour from cv2.findContours')
i = 0
for sq in self.squares:
i += 1
s.append('Square %d : length = %d : area = %d' % (sq.ID, cv2.arcLength(sq.contour, True), sq.area))
return '\n'.join(s)
def process_captcha(self, image):
"""
TODO: DOC
"""
cv2_img = cv2.cvtColor(numpy.array(image), cv2.COLOR_BGR2GRAY)
# Find the threshold of the image so that we can identify contours.
ret, thresh = cv2.threshold(
cv2_img,
127,
255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C
)
# Find the contours of the image
_, contours, hierarchy = cv2.findContours(
thresh,
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE
)
# Find the largest contour in the image with 4 points. This is the
# rectangle that is required to crop to for the captcha.
largest_contour = None
for contour in contours:
if (len(cv2.approxPolyDP(contour, 0.1*cv2.arcLength(contour, True), True)) == 4) and (2500 < cv2.contourArea(contour) < 4000):
if isinstance(largest_contour, type(None)):
largest_contour = contour
continue
if cv2.contourArea(contour) > cv2.contourArea(largest_contour):
largest_contour = contour
# If we don't have a matching contour, don't try to crop and such
if isinstance(largest_contour, type(None)):
return None
# If we do have a matching contour, build the rectangle
crop_x, crop_y, crop_width, crop_height = cv2.boundingRect(
largest_contour
)
# Crop down to the contour rectangle
image = image.crop(
(
crop_x,
crop_y,
crop_x + crop_width,
crop_y + crop_height
)
)
return image
def extract_bv(image):
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
contrast_enhanced_green_fundus = clahe.apply(image)
# applying alternate sequential filtering (3 times closing opening)
r1 = cv2.morphologyEx(contrast_enhanced_green_fundus, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)), iterations = 1)
R1 = cv2.morphologyEx(r1, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)), iterations = 1)
r2 = cv2.morphologyEx(R1, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11)), iterations = 1)
R2 = cv2.morphologyEx(r2, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11)), iterations = 1)
r3 = cv2.morphologyEx(R2, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(23,23)), iterations = 1)
R3 = cv2.morphologyEx(r3, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(23,23)), iterations = 1)
f4 = cv2.subtract(R3,contrast_enhanced_green_fundus)
f5 = clahe.apply(f4)
# removing very small contours through area parameter noise removal
ret,f6 = cv2.threshold(f5,15,255,cv2.THRESH_BINARY)
mask = np.ones(f5.shape[:2], dtype="uint8") * 255
im2, contours, hierarchy = cv2.findContours(f6.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
if cv2.contourArea(cnt) <= 200:
cv2.drawContours(mask, [cnt], -1, 0, -1)
im = cv2.bitwise_and(f5, f5, mask=mask)
ret,fin = cv2.threshold(im,15,255,cv2.THRESH_BINARY_INV)
newfin = cv2.erode(fin, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)), iterations=1)
# removing blobs of microaneurysm & unwanted bigger chunks taking in consideration they are not straight lines like blood
# vessels and also in an interval of area
fundus_eroded = cv2.bitwise_not(newfin)
xmask = np.ones(image.shape[:2], dtype="uint8") * 255
x1, xcontours, xhierarchy = cv2.findContours(fundus_eroded.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt in xcontours:
shape = "unidentified"
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.04 * peri, False)
if len(approx) > 4 and cv2.contourArea(cnt) <= 3000 and cv2.contourArea(cnt) >= 100:
shape = "circle"
else:
shape = "veins"
if(shape=="circle"):
cv2.drawContours(xmask, [cnt], -1, 0, -1)
finimage = cv2.bitwise_and(fundus_eroded,fundus_eroded,mask=xmask)
blood_vessels = cv2.bitwise_not(finimage)
dilated = cv2.erode(blood_vessels, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7)), iterations=1)
#dilated1 = cv2.dilate(blood_vessels, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)), iterations=1)
blood_vessels_1 = cv2.bitwise_not(dilated)
return blood_vessels_1
def extract_bv(image):
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
contrast_enhanced_green_fundus = clahe.apply(image)
# applying alternate sequential filtering (3 times closing opening)
r1 = cv2.morphologyEx(contrast_enhanced_green_fundus, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)), iterations = 1)
R1 = cv2.morphologyEx(r1, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5)), iterations = 1)
r2 = cv2.morphologyEx(R1, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11)), iterations = 1)
R2 = cv2.morphologyEx(r2, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(11,11)), iterations = 1)
r3 = cv2.morphologyEx(R2, cv2.MORPH_OPEN, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(23,23)), iterations = 1)
R3 = cv2.morphologyEx(r3, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(23,23)), iterations = 1)
f4 = cv2.subtract(R3,contrast_enhanced_green_fundus)
f5 = clahe.apply(f4)
# removing very small contours through area parameter noise removal
ret,f6 = cv2.threshold(f5,15,255,cv2.THRESH_BINARY)
mask = np.ones(f5.shape[:2], dtype="uint8") * 255
im2, contours, hierarchy = cv2.findContours(f6.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
if cv2.contourArea(cnt) <= 200:
cv2.drawContours(mask, [cnt], -1, 0, -1)
im = cv2.bitwise_and(f5, f5, mask=mask)
ret,fin = cv2.threshold(im,15,255,cv2.THRESH_BINARY_INV)
newfin = cv2.erode(fin, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)), iterations=1)
# removing blobs of microaneurysm & unwanted bigger chunks taking in consideration they are not straight lines like blood
# vessels and also in an interval of area
fundus_eroded = cv2.bitwise_not(newfin)
xmask = np.ones(image.shape[:2], dtype="uint8") * 255
x1, xcontours, xhierarchy = cv2.findContours(fundus_eroded.copy(),cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
for cnt in xcontours:
shape = "unidentified"
peri = cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, 0.04 * peri, False)
if len(approx) > 4 and cv2.contourArea(cnt) <= 3000 and cv2.contourArea(cnt) >= 100:
shape = "circle"
else:
shape = "veins"
if(shape=="circle"):
cv2.drawContours(xmask, [cnt], -1, 0, -1)
finimage = cv2.bitwise_and(fundus_eroded,fundus_eroded,mask=xmask)
blood_vessels = cv2.bitwise_not(finimage)
dilated = cv2.erode(blood_vessels, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(7,7)), iterations=1)
#dilated1 = cv2.dilate(blood_vessels, cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(3,3)), iterations=1)
blood_vessels_1 = cv2.bitwise_not(dilated)
return blood_vessels_1
def get_contour_perim_by_hull_perim(contour):
return (cv2.arcLength(contour, True) /
cv2.arcLength(get_convex_hull(contour), True))
def get_contour_perim_by_bounding_box_perim(contour):
return (cv2.arcLength(contour, True) /
cv2.arcLength(get_bounding_rect(contour), True))
def _find_hull_defects(self, segment):
# Use cv2 findContours function to find all the contours in segmented img
contours, hierarchy = cv2.findContours(segment, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# assume largest contour is the one of interest
max_contour = max(contours, key=cv2.contourArea)
epsilon = 0.01*cv2.arcLength(max_contour, True)
max_contour = cv2.approxPolyDP(max_contour, epsilon, True)
# determine convex hull & convexity defects of the hull
hull = cv2.convexHull(max_contour, returnPoints=False)
defects = cv2.convexityDefects(max_contour, hull)
return (max_contour, defects)
def __filter_contours(input_contours, min_area, min_perimeter, min_width, max_width,
min_height, max_height, solidity, max_vertex_count, min_vertex_count,
min_ratio, max_ratio):
"""Filters out contours that do not meet certain criteria.
Args:
input_contours: Contours as a list of numpy.ndarray.
min_area: The minimum area of a contour that will be kept.
min_perimeter: The minimum perimeter of a contour that will be kept.
min_width: Minimum width of a contour.
max_width: MaxWidth maximum width.
min_height: Minimum height.
max_height: Maximimum height.
solidity: The minimum and maximum solidity of a contour.
min_vertex_count: Minimum vertex Count of the contours.
max_vertex_count: Maximum vertex Count.
min_ratio: Minimum ratio of width to height.
max_ratio: Maximum ratio of width to height.
Returns:
Contours as a list of numpy.ndarray.
"""
output = []
for contour in input_contours:
x,y,w,h = cv2.boundingRect(contour)
if (w < min_width or w > max_width):
continue
if (h < min_height or h > max_height):
continue
area = cv2.contourArea(contour)
if (area < min_area):
continue
if (cv2.arcLength(contour, True) < min_perimeter):
continue
hull = cv2.convexHull(contour)
solid = 100 * area / cv2.contourArea(hull)
if (solid < solidity[0] or solid > solidity[1]):
continue
if (len(contour) < min_vertex_count or len(contour) > max_vertex_count):
continue
ratio = (float)(w) / h
if (ratio < min_ratio or ratio > max_ratio):
continue
output.append(contour)
return output
def main():
# gets screen size
w, h = pyautogui.size()
# takes screen screenshot. Returns hsv format image
scrn_scrnshot = Screenshot.this(0, 0, w, h, 'hsv')
#cv2.imshow('img', scrn_scrnshot)
# cv2.waitKey(0)
# find Grand exchange window
lower_hsv = np.array([12, 0, 7])
upper_hsv = np.array([40, 62, 64])
# mask of applied values
mask = cv2.inRange(scrn_scrnshot, lower_hsv, upper_hsv)
cv2.imshow('img', mask)
cv2.waitKey(0)
return
# find contours to get sides of rectangle
_, contours, h = cv2.findContours(mask, 1, 2)
for cnt in contours:
# looks for biggest square
# if cv2.contourArea(cnt) <= 1695.0:
# continue
# checks contour sides
approx = cv2.approxPolyDP(cnt, 0.01 * cv2.arcLength(cnt, True), True)
# Square found here vvvv
if len(approx) == 4:
#print("square of {}".format(cv2.contourArea(cnt)))
# cv2.drawContours(rs_window,[cnt],0,(255,255,255),-1)
# get geometry of approx
# add rs coords
x, y, w, h = cv2.boundingRect(cnt)
print(cv2.contourArea(cnt))
def __filter_contours(input_contours, min_area, min_perimeter, min_width, max_width,
min_height, max_height, solidity, max_vertex_count, min_vertex_count,
min_ratio, max_ratio):
"""Filters out contours that do not meet certain criteria.
Args:
input_contours: Contours as a list of numpy.ndarray.
min_area: The minimum area of a contour that will be kept.
min_perimeter: The minimum perimeter of a contour that will be kept.
min_width: Minimum width of a contour.
max_width: MaxWidth maximum width.
min_height: Minimum height.
max_height: Maximimum height.
solidity: The minimum and maximum solidity of a contour.
min_vertex_count: Minimum vertex Count of the contours.
max_vertex_count: Maximum vertex Count.
min_ratio: Minimum ratio of width to height.
max_ratio: Maximum ratio of width to height.
Returns:
Contours as a list of numpy.ndarray.
"""
output = []
for contour in input_contours:
x,y,w,h = cv2.boundingRect(contour)
if (w < min_width or w > max_width):
continue
if (h < min_height or h > max_height):
continue
area = cv2.contourArea(contour)
if (area < min_area):
continue
if (cv2.arcLength(contour, True) < min_perimeter):
continue
hull = cv2.convexHull(contour)
solid = 100 * area / cv2.contourArea(hull)
if (solid < solidity[0] or solid > solidity[1]):
continue
if (len(contour) < min_vertex_count or len(contour) > max_vertex_count):
continue
ratio = (float)(w) / h
if (ratio < min_ratio or ratio > max_ratio):
continue
output.append(contour)
return output
def __filter_contours(input_contours, min_area, min_perimeter, min_width, max_width,
min_height, max_height, solidity, max_vertex_count, min_vertex_count,
min_ratio, max_ratio):
"""Filters out contours that do not meet certain criteria.
Args:
input_contours: Contours as a list of numpy.ndarray.
min_area: The minimum area of a contour that will be kept.
min_perimeter: The minimum perimeter of a contour that will be kept.
min_width: Minimum width of a contour.
max_width: MaxWidth maximum width.
min_height: Minimum height.
max_height: Maximimum height.
solidity: The minimum and maximum solidity of a contour.
min_vertex_count: Minimum vertex Count of the contours.
max_vertex_count: Maximum vertex Count.
min_ratio: Minimum ratio of width to height.
max_ratio: Maximum ratio of width to height.
Returns:
Contours as a list of numpy.ndarray.
"""
output = []
for contour in input_contours:
x,y,w,h = cv2.boundingRect(contour)
if (w < min_width or w > max_width):
continue
if (h < min_height or h > max_height):
continue
area = cv2.contourArea(contour)
if (area < min_area):
continue
if (cv2.arcLength(contour, True) < min_perimeter):
continue
hull = cv2.convexHull(contour)
solid = 100 * area / cv2.contourArea(hull)
if (solid < solidity[0] or solid > solidity[1]):
continue
if (len(contour) < min_vertex_count or len(contour) > max_vertex_count):
continue
ratio = (float)(w) / h
if (ratio < min_ratio or ratio > max_ratio):
continue
output.append(contour)
return output