# Detecting the center of a curved thick line in python using opencv

The images I am working on are like this one

The main goal is to calculate the crease (the blue line like shown in this image)

The idea is that I have to find the center curved line of this image, detect its two extreme points so I can draw the red line, then find the centroid point to draw the blue line I tried the skeleton algorithm:

``````import cv2
import numpy as np
from matplotlib import pyplot as plt
kernel=np.ones((7,7),np.uint8)
# Read the image as a grayscale image
#Threshold the image
ret,img = cv2.threshold(img,100, 255, 0)
imgGray=cv2.GaussianBlur(img,(7,7),0)
# Step 1: Create an empty skeleton
size = np.size(img)
skel = np.zeros(img.shape, np.uint8)

# Get a Cross Shaped Kernel
element = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))

# Repeat steps 2-4
while True:
#Step 2: Open the image
open = cv2.morphologyEx(img, cv2.MORPH_OPEN, element)
#Step 3: Substract open from the original image
temp = cv2.subtract(img, open)
#Step 4: Erode the original image and refine the skeleton
eroded = cv2.erode(img, element)
skel = cv2.bitwise_or(skel,temp)
img = eroded.copy()
# Step 5: If there are no white pixels left ie.. the image has been completely eroded, quit the loop
if cv2.countNonZero(img)==0:
break
``````

and this is what I got:

Now I don’t have access to that center line that I got and I need it so that I can find these three red points

What can I do?

thinning would collapse it to a single line,
from where you can find the maximum y value:

``````# some preprocessing
ocv = cv2.blur(ocv,(9,9))
_,ocv = cv2.threshold(ocv, 220, 255, 0)

# collapse to line
ocv = cv2.ximgproc.thinning(ocv,0)

c, _ = cv2.findContours(ocv,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)

z = np.array(c[0])
z = z.reshape(z.shape[0],z.shape[2]) # remove 'middle' dim
m = np.argmax(z,0) # id of max along 1st dim (y)
id = m[1]
x = z[id,0]
y = z[id,1]
# vizualize
p3 = (int(x),int(y))
cv2.circle(ocv,p3,10,(180))

``````

Here is the complete code

``````def line(p1, p2):
A = (p1[1] - p2[1])
B = (p2[0] - p1[0])
C = (p1[0]*p2[1] - p2[0]*p1[1])
return A, B, -C

def intersection(L1, L2):
D  = L1[0] * L2[1] - L1[1] * L2[0]
Dx = L1[2] * L2[1] - L1[1] * L2[2]
Dy = L1[0] * L2[2] - L1[2] * L2[0]
if D != 0:
x = Dx / D
y = Dy / D
return int(x), int(y)

def detect(image):
# some preprocessing
thin = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
thin = cv2.blur(thin, (10, 10))
_, thin = cv2.threshold(thin, 220, 255, 0)

# thin image to find clear contours
thin = cv2.ximgproc.thinning(thin, thinningType=cv2.ximgproc.THINNING_GUOHALL)

# dind contours
cnts = cv2.findContours(thin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
c = max(cnts, key=cv2.contourArea)

# obtain outer coordinates
left = tuple(c[c[:, :, 0].argmin()][0])
right = tuple(c[c[:, :, 0].argmax()][0])
top = tuple(c[c[:, :, 1].argmin()][0])
bottom = tuple(c[c[:, :, 1].argmax()][0])

# draw connecting line
cv2.line(image, left, right, (0,0,255), 2)

# find the point of intersection
# b/w connecting lines and curve points
l1 = line(left, right)
l2 = line((bottom[0], top[1]), bottom)
inter = intersection(l1, l2)

# draw center curve intersection line
cv2.line(image, inter, bottom, (255, 255, 0), 2)

# draw line contours
cv2.drawContours(image, [c], -1, (36, 255, 12), 2)

return image