Issue
Using opencv with python here is the output of document conture
I'm using opencv_python-4.2.0.34
the bottom left corner is not sharp as the other corners. How to make it right? (edit the bottom left corner automatically to look sharp, as off the others as arise)
here are the code to draw the contour:
img = cv2.imread(imagePath)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
invGamma = 1.0 / 0.3
table = np.array([((i / 255.0) ** invGamma) * 255
for i in np.arange(0, 256)]).astype("uint8")
# apply gamma correction using the lookup table
gray = cv2.LUT(gray, table)
ret, thresh1 = cv2.threshold(gray, 80, 255, cv2.THRESH_BINARY)
contours, hierachy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# except:
# print('exception occurred')
def biggestRectangle(conts):
biggest = None
max_area = 0
indexReturn = -1
for index in range(len(conts)):
i = conts[index]
area = cv2.contourArea(i)
if area > 100:
peri = cv2.arcLength(i, True)
approx = cv2.approxPolyDP(i, 0.1 * peri, True)
if area > max_area and len(approx) == 4:
biggest = approx
max_area = area
indexReturn = index
return indexReturn
indexReturn = biggestRectangle(contours)
hull = cv2.convexHull(contours[indexReturn])
print(indexReturn)
print(contours[indexReturn])
print(hull)
# copyImg = img.copy()
cv2.imwrite(os.path.join('path_to_save', imageName),
cv2.drawContours(img, [hull], 0, (0, 255, 0), 3))
How to make it right. I tried with another approach:
x, y, w, h = cv2.boundingRect(hull)
cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)
newImageName = imageName.split('.')
newImageName = newImageName[0] + '_rect.' + newImageName[1]
print(newImageName)
cv2.imwrite(os.path.join('path_to_save', newImageName), img)
but it's giving me this (the blue outline):
Which is also wrong. How to correct it?
Solution
Since you know that the contour you are interested in is a piece of paper, maybe you can use a more systematic approach to find the largest rotated rectangle using OpenCV's cv2.minAreaRect
(link). It will return the center, size, and rotation of the rectangle that most tightly encloses your contour. Since your image has a pretty difficult background, I had to apply a few more processing steps using OpenCV's morphologyEx function before grabbing the contours, but this this code I could see a better output (shown below).
# first, do some processing
kernel1 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (27, 27))
kernel2 = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13, 13))
thresh1 = cv2.morphologyEx(thresh1, cv2.MORPH_ERODE, kernel1)
thresh1 = cv2.morphologyEx(thresh1, cv2.MORPH_DILATE, kernel2)
# find all contours
contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_LIST,
cv2.CHAIN_APPROX_SIMPLE)
# Find the largest ('max' using the key of the contour area)
biggest_contour = max(contours, key=cv2.contourArea)
# Calculate the minimum enclosing rectangle: format ((x, y), (length, width), angle)
rectangle = cv2.minAreaRect(biggest_contour)
# conver the minAreaRect output to points
pts = cv2.boxPoints(rectangle)
# contours must be of shape (n, 1, 2) and dtype integer
pts = pts.reshape(-1, 1, 2)
pts = pts.astype(int)
# draw contours and display
cv2.drawContours(img, [pts], -1, (255, 0, 0), 2)
cv2.imshow('img', img)
k = cv2.waitKey(0)
Answered By - tiberius
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.