1

I am trying to draw a line into an image but I couldnt. I tried the contours features. I am open to any kind of opinion and help. I am leaving the code I tried to draw but I couldnt draw line.

import time
import cv2
import numpy as np
import sys
sys.maxsize


img = cv2.pyrDown(cv2.imread("ellipse.png", cv2.IMREAD_UNCHANGED))

# threshold image
ret, threshed_img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY),
                127, 255, cv2.THRESH_BINARY)
# find contours and get the external one
contours, hier = cv2.findContours(threshed_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)


for c in contours:
    # get the bounding rect
    x, y, w, h = cv2.boundingRect(c)
    # draw a green rectangle to visualize the bounding rect
    # cv2.rectangle(img, (x, y), (x+w, y+h), (0, 1, 0), 2)

    # get the min area rect
    rect = cv2.minAreaRect(c)
    
    box = cv2.boxPoints(rect)
    # convert all coordinates floating point values to int
    box = np.int0(box)
    # draw a red 'nghien' rectangle
    cv2.drawContours(img, [box], 0, (0, 0, 255))
    


print(len(contours))
cv2.drawContours(img, contours, -1, (255, 255, 0), 1)

cv2.imshow("contours", img)

cv2.imshow("contours", img)

while True:
    key = cv2.waitKey(1)
    if key == 27: #ESC key to break
        break

cv2.destroyAllWindows()
orkayu
  • 17
  • 5

1 Answers1

1

You may fit an ellipse as described in the following post.

Code sample:

import cv2
import numpy as np
import math

img = cv2.pyrDown(cv2.imread("brain_ct.png", cv2.IMREAD_COLOR))

# threshold image
ret, threshed_img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY),
                127, 255, cv2.THRESH_BINARY)
# find contours and get the external one
contours, hier = cv2.findContours(threshed_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # Use cv2.RETR_EXTERNAL for getting the external contour

# find the biggest contour (c) by the area
c = max(contours, key = cv2.contourArea)

(x,y),(MA,ma),angle = cv2.fitEllipse(c)

cv2.ellipse(img, ((x,y), (MA,ma), angle), color=(0, 255, 0), thickness=2)

# https://stackoverflow.com/questions/62698756/opencv-calculating-orientation-angle-of-major-and-minor-axis-of-ellipse
rmajor = max(MA,ma)/2
if angle > 90:
    angle -= 90
else:
    angle += 90
xtop = x + math.cos(math.radians(angle))*rmajor
ytop = y + math.sin(math.radians(angle))*rmajor
xbot = x + math.cos(math.radians(angle+180))*rmajor
ybot = y + math.sin(math.radians(angle+180))*rmajor
cv2.line(img, (int(xtop),int(ytop)), (int(xbot),int(ybot)), (0, 255, 0), 3)

cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Result:
enter image description here

Getting the exact line is a lot harder...


Rotating the image:

  • Set the center to the center of mass:

     # https://stackoverflow.com/questions/49582008/center-of-mass-in-contour-python-opencv
     m = cv2.moments(c)
     cx = int(m["m10"] / m["m00"])
     cy = int(m["m01"] / m["m00"])
     M = cv2.getRotationMatrix2D((cx, cy), angle-90, 1)  # Get transformation         matrix - for rotating by angle, set the center to the center of the ellipse.
    
  • Set the center to the center of the ellipse:

     M = cv2.getRotationMatrix2D((x, y), angle-90, 1)  # Get transformation matrix - for rotating by angle, set the center to the center of the ellipse.
    
     img = cv2.warpAffine(img, M, (img.shape[1], img.shape[0]), cv2.INTER_CUBIC)
    

Result:
enter image description here

Rotem
  • 30,366
  • 4
  • 32
  • 65
  • Thank you so much it worked for me! Do you have any advice for rotating image through angle of line? I want to correct the tilt and make the line vertical. – orkayu May 16 '21 at 10:10
  • You have few options for center selection: The center of the image, the center of mass, and the center of the ellipse. – Rotem May 16 '21 at 10:31
  • You can try using closing morphological operation, but I think the problem requires a very different approach. I don't have an idea right now. You may try posting a new questing, and add a reference to this question. There is a change that someone else finds a solution. – Rotem May 16 '21 at 11:13