It’s the first time I post in this forum and to be honest the first time I post to ask help on a forum for a data science project at all !
So here is my issue. I want to position 6 points on an image of a cylindrical shape to apply a transformation to unbend it (I should be able to do this once I’ve found all my pixel point positions). The image looks like this after a few pre-processing steps:
img = cv2.imread('./img/wine2.jpg') gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) thresh = cv2.adaptiveThreshold(gray_image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 21, 4) contours, hierarchy = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) contour_sizes = [(cv2.contourArea(contour), contour) for contour in contours] cnt = max(contour_sizes, key=lambda x: x) # Create a mask of the label mask = np.zeros(img.shape,np.uint8) cntr = cv2.drawContours(mask, [cnt],0,255,-1) edges = cv2.Canny(cntr ,140, 210)
Ideally I want to position my points like this:
The problem is that I struggle to find a way to do this.
As an example, I’ve tried to detect the left edge to then apply simple loops to get the first pixel at the top and the first pixel at the bottom with some for loops like so:
ddepth = cv2.CV_8U borderType=cv2.BORDER_DEFAULT left = cv2.Sobel(mask,ddepth,1,0,ksize=1,scale=1,delta=0,borderType=borderType) right = cv2.Sobel(mask,ddepth,1,0,ksize=1,scale=-1,delta=0, borderType=borderType) top = cv2.Sobel(mask,ddepth,0,1,ksize=1,scale=1,delta=0,borderType=borderType) bottom = cv2.Sobel(mask,ddepth,0,1,ksize=1,scale=-1,delta=0,borderType=borderType) # Remove noise from borders kernel = np.ones((2,2),np.uint8) left_border = cv2.erode(left,kernel,iterations = 1) right_border = cv2.erode(right,kernel,iterations = 1) top_border = cv2.erode(top,kernel,iterations = 1) bottom_border = cv2.erode(bottom,kernel,iterations = 1) xa = 0 ya = 0 for row in range(left_border.shape): if left_border[row,:].sum() > 0: ya = row break for col in range(left_border.shape): if left_border[:,col].sum() > 0: xa = col break # Getting F point xf = 0 yf = 0 for row in reversed(range(left_border.shape)): if left_border[row,:].sum() > 0: yf = row break
The problem is that even if it worked for the A point, the left border obtained earlier with cv2.erode (hand draw in green) has some noise on top and bottom and as a result when i try to get the yf coordinate by “scanning” my image from the bottom to the top It stops on a little bottom pixel rather than detecting the first bottom pixel of my left geometric border.
So I need your help, should I try to find a way to simplify the representation of my borders ? (smoothing? And if so how ?), or is there a beter method to find a way to automatically position these wanted coordinates ?
I hope I’ve been clear enough, I wish you all to have a nice day !