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

**URL:** <https://forum.opencv.org/t/detecting-the-center-of-a-curved-thick-line-in-python-using-opencv/1909>\
**Category:** Python\
**Tags:** imgproc\
**Created:** [March 2, 2021, 3:14pm UTC](https://forum.opencv.org/t/detecting-the-center-of-a-curved-thick-line-in-python-using-opencv/1909 "2021-03-02T15:14:31Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![fatma\_cheour](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/fatma_cheour/32/1218_2.png) [@fatma\_cheour](https://forum.opencv.org/u/fatma_cheour)\
**Post date:** [March 2, 2021, 3:14pm UTC](https://forum.opencv.org/t/detecting-the-center-of-a-curved-thick-line-in-python-using-opencv/1909/1 "2021-03-02T15:14:31Z")

</div>

The images I am working on are like this one

 ![ss](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/2/28d3b2b3d7eefde83700d2c20ce88959227f2cb4.jpeg)

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

 ![explained](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/c/c6e1d59c52afcbf8342976f8b3e13c569eca101c.jpeg)

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:

```python
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
img = cv2.imread('ressources/ss.jpg', 0)
#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:  
 ![skeleton](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/5/5643810f98a05cd1261f4c72828d09c03b2d099e.png)

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  
 ![skeleton explained](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/a/a73d24f6f49aa555851bf86ff66de271d01074d2.png)

What can I do?

---

<div class="post-metadata">

**Author:** ![berak](https://avatars.discourse-cdn.com/v4/letter/b/85f322/32.png) [@berak](https://forum.opencv.org/u/berak)\
**Post date:** [June 2, 2021, 3:11pm UTC](https://forum.opencv.org/t/detecting-the-center-of-a-curved-thick-line-in-python-using-opencv/1909/3 "2021-06-02T15:11:25Z")

</div>

starting with your original image,  
[thinning](https://docs.opencv.org/master/df/d2d/group__ximgproc.html#ga37002c6ca80c978edb6ead5d6b39740c) would collapse it to a single line,  
from where you can find the maximum y value:

 ![output](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/5/51bcb0533ecc7e364b4d7b0663cc843414abb3a2.jpeg)

```auto
# 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))

```

---

<div class="post-metadata">

**Author:** ![imneonizer](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.opencv.org/imneonizer/32/2506_2.png) [@imneonizer](https://forum.opencv.org/u/imneonizer)\
**Post date:** [June 4, 2021, 2:59pm UTC](https://forum.opencv.org/t/detecting-the-center-of-a-curved-thick-line-in-python-using-opencv/1909/4 "2021-06-04T14:59:44Z")

</div>

Here is the complete code

```python
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

image = cv2.imread("sample.jpg")
output = detect(image)

cv2_imshow(output)

```

Output:  
 ![output](https://us1.discourse-cdn.com/flex020/uploads/opencv/original/2X/d/da71a3288b0c53b9e9b7a25b7d9a50d0a0e10860.jpeg)
