def __bound_contours(roi):
"""
returns modified roi(non-destructive) and rectangles that founded by the algorithm.
@roi region of interest to find contours
@return (roi, rects)
"""
roi_copy = roi.copy()
roi_hsv = cv2.cvtColor(roi, cv2.COLOR_RGB2HSV)
# filter black color
mask1 = cv2.inRange(roi_hsv, np.array([0, 0, 0]), np.array([180, 255, 125]))
mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)))
mask1 = cv2.Canny(mask1, 100, 300)
mask1 = cv2.GaussianBlur(mask1, (1, 1), 0)
mask1 = cv2.Canny(mask1, 100, 300)
# mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)))
# Find contours for detected portion of the image
im2, cnts, hierarchy = cv2.findContours(mask1.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:5] # get largest five contour area
rects = []
for c in cnts:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
x, y, w, h = cv2.boundingRect(approx)
if h >= 15:
# if height is enough
# create rectangle for bounding
rect = (x, y, w, h)
rects.append(rect)
cv2.rectangle(roi_copy, (x, y), (x+w, y+h), (0, 255, 0), 1);
return (roi_copy, rects)
python类CHAIN_APPROX_SIMPLE的实例源码
def find_squares(img):
img = cv2.GaussianBlur(img, (5, 5), 0)
squares = []
for gray in cv2.split(img):
for thrs in xrange(0, 255, 26):
if thrs == 0:
bin = cv2.Canny(gray, 0, 50, apertureSize=5)
bin = cv2.dilate(bin, None)
else:
retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
bin, contours, hierarchy = cv2.findContours(bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
cnt_len = cv2.arcLength(cnt, True)
cnt = cv2.approxPolyDP(cnt, 0.02 * cnt_len, True)
if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos(cnt[i], cnt[(i + 1) % 4], cnt[(i + 2) % 4]) for i in xrange(4)])
if max_cos < 0.1:
squares.append(cnt)
return squares
def find_biggest_contour(image):
# Copy
image = image.copy()
#input, gives all the contours, contour approximation compresses horizontal,
#vertical, and diagonal segments and leaves only their end points. For example,
#an up-right rectangular contour is encoded with 4 points.
#Optional output vector, containing information about the image topology.
#It has as many elements as the number of contours.
#we dont need it
_, contours, hierarchy = cv2.findContours(image, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# Isolate largest contour
contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours]
biggest_contour = max(contour_sizes, key=lambda x: x[0])[1]
mask = np.zeros(image.shape, np.uint8)
cv2.drawContours(mask, [biggest_contour], -1, 255, -1)
return biggest_contour, mask
def remove_borders(image):
ratio = image.shape[0] / 500.0
orig = image.copy()
image = resize(image, height=500)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (5, 5), 0)
edged = cv2.Canny(gray, 75, 200)
_, cnts, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cv2.imshow('edged', edged)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
screenCnt = None
for c in cnts:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
print(len(approx) == 4)
if len(approx) == 4:
screenCnt = approx
break
cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)
if screenCnt is not None and len(screenCnt) > 0:
return four_point_transform(orig, screenCnt.reshape(4, 2) * ratio)
return orig
def extract_corners(self, image):
"""
Find the 4 corners of a binary image
:param image: binary image
:return: 4 main vertices or None
"""
cnts, _ = cv2.findContours(image.copy(),
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[-2:]
cnt = cnts[0]
_, _, h, w = cv2.boundingRect(cnt)
epsilon = min(h, w) * 0.5
vertices = cv2.approxPolyDP(cnt, epsilon, True)
vertices = cv2.convexHull(vertices, clockwise=True)
vertices = self.correct_vertices(vertices)
return vertices
def find_squares(img):
img = cv2.GaussianBlur(img, (5, 5), 0)
squares = []
for gray in cv2.split(img):
for thrs in xrange(0, 255, 26):
if thrs == 0:
bin = cv2.Canny(gray, 0, 50, apertureSize=5)
bin = cv2.dilate(bin, None)
else:
_retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
contours, _hierarchy = find_contours(bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
x, y, w, h = cv2.boundingRect(cnt)
cnt_len = cv2.arcLength(cnt, True)
cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
area = cv2.contourArea(cnt)
if len(cnt) == 4 and 20 < area < 1000 and cv2.isContourConvex(cnt):
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in xrange(4)])
if max_cos < 0.1:
if (1 - (float(w) / float(h)) <= 0.07 and 1 - (float(h) / float(w)) <= 0.07):
squares.append(cnt)
return squares
def find_squares(img, cos_limit = 0.1):
print('search for squares with threshold %f' % cos_limit)
img = cv2.GaussianBlur(img, (5, 5), 0)
squares = []
for gray in cv2.split(img):
for thrs in xrange(0, 255, 26):
if thrs == 0:
bin = cv2.Canny(gray, 0, 50, apertureSize=5)
bin = cv2.dilate(bin, None)
else:
retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
bin, contours, hierarchy = cv2.findContours(bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for cnt in contours:
cnt_len = cv2.arcLength(cnt, True)
cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
if len(cnt) == 4 and cv2.contourArea(cnt) > 1000 and cv2.isContourConvex(cnt):
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in xrange(4)])
if max_cos < cos_limit :
squares.append(cnt)
else:
#print('dropped a square with max_cos %f' % max_cos)
pass
return squares
###
### Version V2. Collect meta-data along the way, with commentary added.
###
def find_contours(self, img):
thresh_img = self.threshold(img)
_, contours, _ = cv2.findContours(thresh_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
result = []
for cnt in contours:
approx = cv2.approxPolyDP(cnt, 0.01*cv2.arcLength(cnt, True), True)
if self.draw_approx:
cv2.drawContours(self.out, [approx], -1, self.BLUE, 2, lineType=8)
if len(approx) > 3 and len(approx) < 15:
_, _, w, h = cv2.boundingRect(approx)
if h > self.min_height and w > self.min_width:
hull = cv2.convexHull(cnt)
approx2 = cv2.approxPolyDP(hull,0.01*cv2.arcLength(hull,True),True)
if self.draw_approx2:
cv2.drawContours(self.out, [approx2], -1, self.GREEN, 2, lineType=8)
result.append(approx2)
return result
def find_center(self, name, frame, mask, min_radius):
if name not in self.pts:
self.pts[name] = deque(maxlen=self.params['tracking']['buffer_size'])
# find contours in the mask and initialize the current (x, y) center of the ball
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[-2]
# only proceed if at least one contour was found
if len(cnts) > 0:
# find the largest contour in the mask, then use it to compute the minimum enclosing circle and centroid
c = max(cnts, key=cv2.contourArea)
((x, y), radius) = cv2.minEnclosingCircle(c)
center = (int(x), int(y))
# only proceed if the radius meets a minimum size
if radius > min_radius:
# draw the circle and centroid on the frame, then update the list of tracked points
cv2.circle(frame, center, int(radius), (0, 255, 255), 2)
cv2.circle(frame, center, 5, (0, 0, 255), -1)
self.pts[name].appendleft(center)
smooth_points = 8
return (int(np.mean([self.pts[name][i][0] for i in range(min(smooth_points, len(self.pts[name])))])),
int(np.mean([self.pts[name][i][1] for i in range(min(smooth_points, len(self.pts[name])))]))), radius
return None, None
Artificial-potential-controller-2.py 文件源码
项目:Artificial-Potential-Field
作者: vampcoder
项目源码
文件源码
阅读 24
收藏 0
点赞 0
评论 0
def classify(img):
cimg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img2 = cv2.medianBlur(cimg, 13)
ret, thresh1 = cv2.threshold(cimg, 100, 120, cv2.THRESH_BINARY)
t2 = copy.copy(thresh1)
x, y = thresh1.shape
arr = np.zeros((x, y, 3), np.uint8)
final_contours = []
image, contours, hierarchy = cv2.findContours(t2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#cv2.imshow('image', image)
#k = cv2.waitKey(0)
for i in range(len(contours)):
cnt = contours[i]
if cv2.contourArea(cnt) > 3000 and cv2.contourArea(cnt) < 25000:
cv2.drawContours(img, [cnt], -1, [0, 255, 255])
cv2.fillConvexPoly(arr, cnt, [255, 255, 255])
final_contours.append(cnt)
#cv2.imshow('arr', arr)
#k = cv2.waitKey(0)
return arr
def diagContour(image):
#Find contours in the image the first and last returns dont matter so the _ is just a placeholder to ignore them
_, contours, _ = cv2.findContours(image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#The contouring operation does some weird stuff to the image so this line just fills the whole thing with black
image.fill(0)
boundingRect = []
firstFail = []
#Loops through all contours bigger than minArea pixels. That number is tweakable and determined by testing
for j in [i for i in contours if cv2.contourArea(i) > minArea]:
#br is a (list/tuple)? of the form x, y, width, height where (x,y) is the (top/bottom)? (left/right)? corner
br = cv2.boundingRect(j)
if(abs(br[2]/br[3] - INDASPECT) < indAspectTol and cv2.contourArea(j)/(br[2]*br[3]) > covTol):
boundingRect.append(br)
else:
firstFail.append([br, br[2]/br[3], cv2.contourArea(j)/(br[2]*br[3])])
secondRound = []
for x in range(0, len(boundingRect)):
for y in range(x+1, len(boundingRect)):
i = boundingRect[x]
j = boundingRect[y]
secondRound.append([(x,y,i,j), (abs(i[1]-j[1]), i[3]/2), abs(i[0]-j[0])/i[1]])
for x in secondRound:
if(x[1][0] < x[1][1] and x[2] - GRPASPECT < grpAspectTol):
return [x[0][2], x[0][3]]
return None;
def findEllipses(edges):
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
ellipseMask = np.zeros(edges.shape, dtype=np.uint8)
contourMask = np.zeros(edges.shape, dtype=np.uint8)
pi_4 = np.pi * 4
for i, contour in enumerate(contours):
if len(contour) < 5:
continue
area = cv2.contourArea(contour)
if area <= 100: # skip ellipses smaller then 10x10
continue
arclen = cv2.arcLength(contour, True)
circularity = (pi_4 * area) / (arclen * arclen)
ellipse = cv2.fitEllipse(contour)
poly = cv2.ellipse2Poly((int(ellipse[0][0]), int(ellipse[0][1])), (int(ellipse[1][0] / 2), int(ellipse[1][1] / 2)), int(ellipse[2]), 0, 360, 5)
# if contour is circular enough
if circularity > 0.6:
cv2.fillPoly(ellipseMask, [poly], 255)
continue
# if contour has enough similarity to an ellipse
similarity = cv2.matchShapes(poly.reshape((poly.shape[0], 1, poly.shape[1])), contour, cv2.cv.CV_CONTOURS_MATCH_I2, 0)
if similarity <= 0.2:
cv2.fillPoly(contourMask, [poly], 255)
return ellipseMask, contourMask
def get_contours(image, polydb=0.1, contour_range=7):
# 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]]])
return screenCnt
def GetImageContour(self):
thresholdImage = self.__convertImagetoBlackWhite() #B & W with adaptive threshold
thresholdImage = cv.Canny(thresholdImage, 100, 200) #Edges by canny edge detection
thresholdImage, contours, hierarchy = cv.findContours(
thresholdImage, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
self.Contours = contours
# uncomment this to see the contours on the image
# cv2.drawContours(thresholdImage, contours, -1, (0,255,0), 3)
# patternFindingObj=PatternFinding()
# areas= [cv.contourArea(contour) for contour in contours]
# for index in xrange(len(contours)):
# IsPattern=self.IsPossibleQRContour(index)
# if IsPattern is True:
# x,y,w,h=cv.boundingRect(contours[index])
# cv.rectangle(self.imageOriginal,(x,y),(x+w,y+h),(0,0,255),2)
# cv.imshow("hello",self.imageOriginal)
# maxAreaIndex=np.argmax(areas)
# x,y,w,h=cv.boundingRect(contours[maxAreaIndex])
# cv.rectangle(self.image2,(x,y),(x+w,y+h),(0,255,0),2)
# cv.imshow("hello",self.imageOriginal)
# cv.waitKey(0)
#cv.destroyAllWindows()
contour_group = (thresholdImage, contours, hierarchy)
return contour_group
def findSquare( self,frame ):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (7, 7), 0)
edged = cv2.Canny(blurred, 60, 60)
# find contours in the edge map
(cnts, _) = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# loop over our contours to find hexagon
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:50]
screenCnt = None
for c in cnts:
# approximate the contour
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.004 * peri, True)
# if our approximated contour has four points, then
# we can assume that we have found our squeare
if len(approx) >= 4:
screenCnt = approx
x,y,w,h = cv2.boundingRect(c)
cv2.drawContours(image, [approx], -1, (0, 0, 255), 1)
#cv2.imshow("Screen", image)
#create the mask and remove rest of the background
mask = np.zeros(image.shape[:2], dtype = "uint8")
cv2.drawContours(mask, [screenCnt], -1, 255, -1)
masked = cv2.bitwise_and(image, image, mask = mask)
#cv2.imshow("Masked",masked )
#crop the masked image to to be compared to referance image
cropped = masked[y:y+h,x:x+w]
#scale the image so it is fixed size as referance image
cropped = cv2.resize(cropped, (200,200), interpolation =cv2.INTER_AREA)
return cropped
def extract_corners(self, image):
"""
Find the 4 corners of a binary image
:param image: binary image
:return: 4 main vertices or None
"""
cnts, _ = cv2.findContours(image.copy(),
cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[-2:]
cnt = cnts[0]
_, _, h, w = cv2.boundingRect(cnt)
epsilon = min(h, w) * 0.5
o_vertices = cv2.approxPolyDP(cnt, epsilon, True)
vertices = cv2.convexHull(o_vertices, clockwise=True)
vertices = self.correct_vertices(vertices)
if self.debug:
temp = cv2.cvtColor(image.copy(), cv2.COLOR_GRAY2BGR)
cv2.drawContours(temp, cnts, -1, (0, 255, 0), 10)
cv2.drawContours(temp, o_vertices, -1, (255, 0, 0), 30)
cv2.drawContours(temp, vertices, -1, (0, 0, 255), 20)
self.save2image(temp)
return vertices
def imgSeg_contour(img, b,g,r, per):
lower = np.array([0, 0, 0])
upper = np.array([b,g,r])
shapeMask = cv2.inRange(img, lower, upper)
#http://stackoverflow.com/questions/27746089/python-computer-vision-contours-too-many-values-to-unpack
_, cnts, hierarchy = cv2.findContours(shapeMask.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key = cv2.contourArea, reverse = True)[:4]
for c in cnts:
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, per * peri, True) ### 0.04 ###
if (len(approx) >= 4) and (len(approx) < 6):
break
return approx
def shapeFiltering(img):
contours = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]
if len(contours) == 0:
print "shapeFiltering: Error, no contours found"
return 1
good_shape = []
for c in contours:
x,y,w,h = cv2.boundingRect(c)
#if h == 0:
# continue
ratio = w / h
ratio_grade = ratio / (TMw / TMh)
if 0.2 < ratio_grade < 1.8:
good_shape.append(c)
return good_shape
BoundaryExtraction.py 文件源码
项目:SummerProject_MacularDegenerationDetection
作者: WDongYuan
项目源码
文件源码
阅读 20
收藏 0
点赞 0
评论 0
def EdgeDetection(img):
img = cv2.fastNlMeansDenoising(img,None,3,7,21)
_,img = cv2.threshold(img,30,255,cv2.THRESH_TOZERO)
denoise_img = img
laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5) # x
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) # y
canny = cv2.Canny(img,100,200)
contour_image, contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
return {"denoise":denoise_img,"laplacian":laplacian,"canny":canny,"sobely":sobely,"sobelx":sobelx,"contour":contour_image}
# GrayScale Image Convertor
# https://extr3metech.wordpress.com
BoundaryExtraction.py 文件源码
项目:SummerProject_MacularDegenerationDetection
作者: WDongYuan
项目源码
文件源码
阅读 28
收藏 0
点赞 0
评论 0
def EdgeDetection(img):
img = cv2.fastNlMeansDenoising(img,None,3,7,21)
_,img = cv2.threshold(img,30,255,cv2.THRESH_TOZERO)
denoise_img = img
laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5) # x
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3) # y
canny = cv2.Canny(img,100,200)
contour_image, contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
return {"denoise":denoise_img,"laplacian":laplacian,"canny":canny,"sobely":sobely,"sobelx":sobelx,"contour":contour_image}
# GrayScale Image Convertor
# https://extr3metech.wordpress.com
def cannyThresholding(self, contour_retrieval_mode = cv2.RETR_LIST):
'''
contour_retrieval_mode is passed through as second argument to cv2.findContours
'''
# Attempt to match edges found in blue, green or red channels : collect all
channel = 0
for gray in cv2.split(self.img):
channel += 1
print('channel %d ' % channel)
title = self.tgen.next('channel-%d' % channel)
if self.show: ImageViewer(gray).show(window = title, destroy = self.destroy, info = self.info, thumbnailfn = title)
found = {}
for thrs in xrange(0, 255, 26):
print('Using threshold %d' % thrs)
if thrs == 0:
print('First step')
bin = cv2.Canny(gray, 0, 50, apertureSize=5)
title = self.tgen.next('canny-%d' % channel)
if self.show: ImageViewer(bin).show(window = title, destroy = self.destroy, info = self.info, thumbnailfn = title)
bin = cv2.dilate(bin, None)
title = self.tgen.next('canny-dilate-%d' % channel)
if self.show: ImageViewer(bin).show(window = title, destroy = self.destroy, info = self.info, thumbnailfn = title)
else:
retval, bin = cv2.threshold(gray, thrs, 255, cv2.THRESH_BINARY)
title = self.tgen.next('channel-%d-threshold-%d' % (channel, thrs))
if self.show: ImageViewer(bin).show(window='Next threshold (n to continue)', destroy = self.destroy, info = self.info, thumbnailfn = title)
bin, contours, hierarchy = cv2.findContours(bin, contour_retrieval_mode, cv2.CHAIN_APPROX_SIMPLE)
title = self.tgen.next('channel-%d-threshold-%d-contours' % (channel, thrs))
if self.show: ImageViewer(bin).show(window = title, destroy = self.destroy, info = self.info, thumbnailfn = title)
if contour_retrieval_mode == cv2.RETR_LIST or contour_retrieval_mode == cv2.RETR_EXTERNAL:
filteredContours = contours
else:
filteredContours = []
h = hierarchy[0]
for component in zip(contours, h):
currentContour = component[0]
currentHierarchy = component[1]
if currentHierarchy[3] < 0:
# Found the outermost parent component
filteredContours.append(currentContour)
print('Contours filtered. Input %d Output %d' % (len(contours), len(filteredContours)))
time.sleep(5)
for cnt in filteredContours:
cnt_len = cv2.arcLength(cnt, True)
cnt = cv2.approxPolyDP(cnt, 0.02*cnt_len, True)
cnt_len = len(cnt)
cnt_area = cv2.contourArea(cnt)
cnt_isConvex = cv2.isContourConvex(cnt)
if cnt_len == 4 and (cnt_area > self.area_min and cnt_area < self.area_max) and cnt_isConvex:
cnt = cnt.reshape(-1, 2)
max_cos = np.max([angle_cos( cnt[i], cnt[(i+1) % 4], cnt[(i+2) % 4] ) for i in xrange(4)])
if max_cos < self.cos_limit :
sq = Square(cnt, cnt_area, cnt_isConvex, max_cos)
self.squares.append(sq)
else:
#print('dropped a square with max_cos %f' % max_cos)
pass
found[thrs] = len(self.squares)
print('Found %d quadrilaterals with threshold %d' % (len(self.squares), thrs))
def test_initial_pass_through_compare(self):
original = cv2.imread(os.path.join(self.provider.assets, "start_screen.png"))
against = self.provider.get_img_from_screen_shot()
wrong = cv2.imread(os.path.join(self.provider.assets, "battle.png"))
# convert the images to grayscale
original = mask_image([127], [255], cv2.cvtColor(original, cv2.COLOR_BGR2GRAY), True)
against = mask_image([127], [255], cv2.cvtColor(against, cv2.COLOR_BGR2GRAY), True)
wrong = mask_image([127], [255], cv2.cvtColor(wrong, cv2.COLOR_BGR2GRAY), True)
# initialize the figure
(score, diff) = compare_ssim(original, against, full=True)
diff = (diff * 255).astype("uint8")
self.assertTrue(score > .90, 'If this is less then .90 the initial compare of the app will fail')
(score, nothing) = compare_ssim(original, wrong, full=True)
self.assertTrue(score < .90)
if self.__debug_pictures__:
# threshold the difference image, followed by finding contours to
# obtain the regions of the two input images that differ
thresh = cv2.threshold(diff, 0, 255,
cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0]
# loop over the contours
for c in cnts:
# compute the bounding box of the contour and then draw the
# bounding box on both input images to represent where the two
# images differ
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(original, (x, y), (x + w, y + h), (0, 0, 255), 2)
cv2.rectangle(against, (x, y), (x + w, y + h), (0, 0, 255), 2)
# show the output images
diffs = ("Original", original), ("Modified", against), ("Diff", diff), ("Thresh", thresh)
images = ("Original", original), ("Against", against), ("Wrong", wrong)
self.setup_compare_images(diffs)
self.setup_compare_images(images)
def findSignificantContours(img, sobel_8u, sobel):
image, contours, heirarchy = cv2.findContours(sobel_8u, \
cv2.RETR_EXTERNAL, \
cv2.CHAIN_APPROX_SIMPLE)
mask = np.ones(image.shape[:2], dtype="uint8") * 255
level1 = []
for i, tupl in enumerate(heirarchy[0]):
if tupl[3] == -1:
tupl = np.insert(tupl, 0, [i])
level1.append(tupl)
significant = []
tooSmall = sobel_8u.size * 10 / 100
for tupl in level1:
contour = contours[tupl[0]];
area = cv2.contourArea(contour)
if area > tooSmall:
cv2.drawContours(mask, \
[contour], 0, (0, 255, 0), \
2, cv2.LINE_AA, maxLevel=1)
significant.append([contour, area])
significant.sort(key=lambda x: x[1])
significant = [x[0] for x in significant];
peri = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.02 * peri, True)
mask = sobel.copy()
mask[mask > 0] = 0
cv2.fillPoly(mask, significant, 255, 0)
mask = np.logical_not(mask)
img[mask] = 0;
return img
def draw_contours(self):
""""""
# contours all the objects found
# (findContours changes the source image,
# hence copy)
contours, _ = cv2.findContours(self.mask.copy(),
cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
# rectangles
for contour in contours:
size = cv2.contourArea(contour)
if size > self.threshold: # only larger objects
ret_x, ret_y, ret_w, ret_h = cv2.boundingRect(contour)
cv2.rectangle(self.display, (ret_x, ret_y),
(ret_x+ret_w,
ret_y+ret_h),
(0, 255, 255), 2)
def find_contours(mask, smooth_factor=0.005):
""" Find the contours in a given mask """
border = 5
# Canny detection breaks down with the edge of the image
my_mask = cv2.copyMakeBorder(mask, border, border, border, border,
cv2.BORDER_CONSTANT, value=(0, 0, 0))
my_mask = cv2.cvtColor(my_mask, cv2.COLOR_BGR2GRAY)
if is_cv2():
contours, _ = cv2.findContours(my_mask, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
else:
_, contours, _ = cv2.findContours(my_mask, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
# shift the contours back down
for contour in contours:
for pnt in contour:
if pnt[0][1] > border:
pnt[0][1] = pnt[0][1] - border
else:
pnt[0][1] = 0
if pnt[0][0] > border:
pnt[0][0] = pnt[0][0] - border
else:
pnt[0][0] = 0
closed_contours = []
for contour in contours:
epsilon = smooth_factor*cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
area = cv2.contourArea(approx)
# if they are too small they are not edges
if area < 200:
continue
closed_contours.append(approx)
return closed_contours
def find_components(im, max_components=16):
"""Dilate the image until there are just a few connected components.
Returns contours for these components."""
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))
dilation = dilate(im, kernel, 6)
count = 21
n = 0
sigma = 0.000
while count > max_components:
n += 1
sigma += 0.005
result = cv2.findContours(dilation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
if len(result) == 3:
_, contours, hierarchy = result
elif len(result) == 2:
contours, hierarchy = result
possible = find_likely_rectangles(contours, sigma)
count = len(possible)
return (dilation, possible, n)
find_rect_and_transform.py 文件源码
项目:quadrilaterals-rectifier
作者: michal2229
项目源码
文件源码
阅读 24
收藏 0
点赞 0
评论 0
def extract_rect(im):
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# finding contour with max area
largest = None
for cnt in contours:
if largest == None or cv2.contourArea(cnt) > cv2.contourArea(largest):
largest = cnt
peri = cv2.arcLength(largest, True)
appr = cv2.approxPolyDP(largest, 0.02 * peri, True)
#cv2.drawContours(im, appr, -1, (0,255,0), 3)
points_list = [[i[0][0], i[0][1]] for i in appr]
left = sorted(points_list, key = lambda p: p[0])[0:2]
right = sorted(points_list, key = lambda p: p[0])[2:4]
print("l " + str(left))
print("r " + str(right))
lu = sorted(left, key = lambda p: p[1])[0]
ld = sorted(left, key = lambda p: p[1])[1]
ru = sorted(right, key = lambda p: p[1])[0]
rd = sorted(right, key = lambda p: p[1])[1]
print("lu " + str(lu))
print("ld " + str(ld))
print("ru " + str(ru))
print("rd " + str(rd))
lu_ = [ (lu[0] + ld[0])/2, (lu[1] + ru[1])/2 ]
ld_ = [ (lu[0] + ld[0])/2, (ld[1] + rd[1])/2 ]
ru_ = [ (ru[0] + rd[0])/2, (lu[1] + ru[1])/2 ]
rd_ = [ (ru[0] + rd[0])/2, (ld[1] + rd[1])/2 ]
print("lu_ " + str(lu_))
print("ld_ " + str(ld_))
print("ru_ " + str(ru_))
print("rd_ " + str(rd_))
src_pts = np.float32(np.array([lu, ru, rd, ld]))
dst_pts = np.float32(np.array([lu_, ru_, rd_, ld_]))
h,w,b = im.shape
H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
print("H" + str(H))
imw = cv2.warpPerspective(im, H, (w, h))
return imw[lu_[1]:rd_[1], lu_[0]:rd_[0]] # cropping image
def recognize_text(original):
idcard = original
gray = cv2.cvtColor(idcard, cv2.COLOR_BGR2GRAY)
# Morphological gradient:
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
opening = cv2.morphologyEx(gray, cv2.MORPH_GRADIENT, kernel)
# Binarization
ret, binarization = cv2.threshold(opening, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
# Connected horizontally oriented regions
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
connected = cv2.morphologyEx(binarization, cv2.MORPH_CLOSE, kernel)
# find countours
_, contours, hierarchy = cv2.findContours(
connected, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE
)
return contours, hierarchy
def find_components(edges, max_components=16):
"""Dilate the image until there are just a few connected components.
Returns contours for these components."""
# Perform increasingly aggressive dilation until there are just a few
# connected components.
count = 21
dilation = 5
n = 1
while count > 16:
n += 1
dilated_image = dilate(edges, N=3, iterations=n)
_, contours, hierarchy = cv2.findContours(dilated_image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
count = len(contours)
#print dilation
#Image.fromarray(edges).show()
#Image.fromarray(255 * dilated_image).show()
return contours
def _find_size_candidates(self, image):
binary_image = self._filter_image(image)
_, contours, _ = cv2.findContours(binary_image,
cv2.RETR_LIST,
cv2.CHAIN_APPROX_SIMPLE)
size_candidates = []
for contour in contours:
bounding_rect = cv2.boundingRect(contour)
contour_area = cv2.contourArea(contour)
if self._is_valid_contour(contour_area, bounding_rect):
candidate = (bounding_rect[2] + bounding_rect[3]) / 2
size_candidates.append(candidate)
return size_candidates