Problem
I am working on a project where I need to get bounding rectangles with similar shapes. However, I need fewer possible points, and the boxes must fit the shapes in all corners. Here is the image I made for checking: Blurred, cracked, dumbbell shapes
I donβt care that the spaces go into the form, I just want to clear them and straighten the edges to get the contours of this shape:
I am trying to do threshold() by getting its outlines using findContours() and then using approxPolyDP() to simplify the crazy amount of points that are concussing. So, after I started doing this for three days, how can I just get:
- Two fields indicating the ends of the dumbbell and the rectangle in the middle, or
- One contour with twelve points for all angles
The second option would be preferable, since this is really my ultimate goal: to get the points that are at these corners.
A few notes:
- I am using OpenCV for Python
- As a rule, many of these forms of all types will be displayed on all input images.
- They will only have horizontal or vertical positioning. No weird 27 degree angles ...
What I need:
I really don't need someone to write the code for me, I just need some method or algorithm to do this, preferably with some simple examples.
My code
Here is my overly clean code with functions that I donβt even use, but with a digit I would use them in the end:
import cv2 import numpy as np class traceImage(): def __init__(self, imageLocation): self.threshNum = 127 self.im = cv2.imread(imageLocation) self.imOrig = self.im self.imGray = cv2.cvtColor(self.im, cv2.COLOR_BGR2GRAY) self.ret, self.imThresh = cv2.threshold(self.imGray, self.threshNum, 255, 0) self.contours, self.hierarchy = cv2.findContours(self.imThresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) def createGray(self): self.imGray = cv2.cvtColor(self.im, cv2.COLOR_BGR2GRAY) def adjustThresh(self, threshNum): self.ret, self.imThresh = cv2.threshold(self.imGray, threshNum, 255, 0) def getContours(self): self.contours, self.hierarchy = cv2.findContours(self.imThresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) def approximatePoly(self, percent): i=0 for shape in self.contours: shape = cv2.approxPolyDP(shape, percent*cv2.arcLength(shape, True), True) self.contours[i] = shape i+=1 def drawContours(self, blobWidth, color=(255,255,255)): cv2.drawContours(self.im, self.contours, -1, color, blobWidth) def newWindow(self, name): cv2.namedWindow(name) def showImage(self, window): cv2.imshow(window, self.im) def display(self): while True: cv2.waitKey() def displayUntil(self, key): while True: pressed = cv2.waitKey() if pressed == key: break if __name__ == "__main__": blobWidth = 30 ti = traceImage("dumbell.png") ti.approximatePoly(0.01) for thresh in range(127,256): ti.adjustThresh(thresh) ti.getContours() ti.drawContours(blobWidth) ti.showImage("Image") ti.displayUntil(10) ti.createGray() ti.adjustThresh(127) ti.getContours() ti.approximatePoly(0.0099) ti.drawContours(2, (0,255,0)) ti.showImage("Image") ti.display()
Code Explanation
I know that I may not be doing something right here, but hey, I'm proud of it :)
So, the idea is that in these dumbbells there are often holes and gaps, so I decided that if I repeated all threshold values ββfrom 127 to 255 and drew the outlines on the image with a sufficiently large thickness, any thickness for drawing outlines would be filled the holes are small enough and I could use a new, bobby image to get the edges and then scale the sides to size. That was my thinking. There should be another one, bitter, though ...
Summary
I want to finish with 12 points; one for each corner of the form.
EDIT:
After overturning some erosion and dilatation, it seems that the best option would be to cut the contours at certain points, and then use the bounding rectangles around the cut shapes to get the correct square corners, and then do some calculations to get back to the boxes in one shape. Pretty interesting task ...
EDIT 2:
I found something that works well! I made my own line detection system that detects only horizontal or vertical lines, and then on the detected edge of the line / path, the program draws a black line that runs along the entire image, thereby effectively cutting the image along the straight lines of the path. Once he does, he gets the new outlines of the cut boxes, draws bounding rectangles around the pieces, and then uses the extension to close the gaps. So far, it works well on large forms, but when the pieces are small, it tends to lose a little shape.