HoughLines can't find line on simple case

I have a simple case of a rotated rectangle, and I expect houghline function to give me the borders of that rectangle. But it only give me one border. I cannot make the threshold too low or it will get too many noise line on other cases. I also think this case is simple enough for algorithm to find borders. Do any one have some advices? Thank you

  • original image
    img

I expect to get both border of two axis

def line(img_):
    dst = cv.Canny(img_, 50, 200, None, 3)
    print("canny")
    plt.imshow(dst)
    plt.show()
    # Copy edges to the images that will display the results in BGR
    cdst = cv.cvtColor(dst, cv.COLOR_GRAY2BGR)
    cdstP = np.copy(cdst)
    lines = cv.HoughLines(dst, 4, np.pi / 90, 60)
    thetas_h = []
    thetas_v = []
    if lines is not None:
        for i in range(0, len(lines)):
            rho = lines[i][0][0]
            theta = lines[i][0][1]
            print(theta)
            if (theta > np.pi / 4) and (theta < np.pi*3 / 4):
                thetas_h.append(theta)
                a = math.cos(theta)
                b = math.sin(theta)
                x0 = a * rho
                y0 = b * rho
                pt1 = (int(x0 + 1000*(-b)), int(y0 + 1000*(a)))
                pt2 = (int(x0 - 1000*(-b)), int(y0 - 1000*(a)))
                cv.line(cdst, pt1, pt2, (255,0,0), 3, cv.LINE_AA)
            else:
                theta = np.pi/2 - abs(theta - np.pi/2)
                thetas_v.append(theta)
                a = math.cos(theta)
                b = math.sin(theta)
                x0 = a * rho
                y0 = b * rho
                pt1 = (int(x0 + 1000*(-b)), int(y0 + 1000*(a)))
                pt2 = (int(x0 - 1000*(-b)), int(y0 - 1000*(a)))
                cv.line(cdst, pt1, pt2, (0,255,0), 3, cv.LINE_AA)
    
    
    print("thetas_h",thetas_h)
    print("thetas_v",thetas_v)
    plt.imshow(cdst)
    plt.show()
    return (thetas_h, thetas_v)
img = cv2.imread("img.jpg")
(thetas_h, thetas_v) = line(img)

welcome.

please demonstrate your issue with minimal but complete source code and required data. your demonstration must be runnable by other people.

You don’t need this cv.HoughLines. You simply want to draw a rectangle with specified rotation.
Here is code:

import cv2
import numpy as np

OPENCV_MAJOR_VERSION = int(cv2.__version__.split('.')[0])

img = cv2.pyrDown(cv2.imread("box.jpg", cv2.IMREAD_UNCHANGED))

ret, thresh = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY),
                            127, 255, cv2.THRESH_BINARY)

if OPENCV_MAJOR_VERSION >= 4:
    # OpenCV 4 or a later version is being used.
    contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL,
                                      cv2.CHAIN_APPROX_SIMPLE)
else:
    # OpenCV 3 or an earlier version is being used.
    # cv2.findContours has an extra return value.
    # The extra return value is the thresholded image, which is
    # unchanged, so we can ignore it.
    _, contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL,
                                         cv2.CHAIN_APPROX_SIMPLE)

for c in contours:
    # find minimum area
    rect = cv2.minAreaRect(c)
    # calculate coordinates of the minimum area rectangle
    box = cv2.boxPoints(rect)
    # normalize coordinates to integers
    box = np.int0(box)
    # draw contours
    cv2.drawContours(img, [box], 0, (0,0, 255), 2)

cv2.imshow("contours", img)

cv2.waitKey(0)
cv2.destroyAllWindows()

I know this contour method, but I’m wondering why Hough method cannot deal with this simple case. Also, efficiency is one of my major concern. I have heard that contour method is complicated, but have no idea how it compares to Hough method.

Hough method doesn’t do for you. You have to write manually.

Hough is computationally intensive if you pick the wrong parameters. it’s also difficult to get good results. newbies usually get stuck on it because they think it is useful. that is a trap.

findContours doesn’t cost too much.

please simplify your code. what is the result of HoughLines you get? all that follows in your first post is a distraction.

this is what I get with your picture and code:

array([[[ 6.     ,  1.67552]],

       [[10.     ,  1.6057 ]]], dtype=float32)

two lines, same rough distance and orientation, okay, so maybe your coefficients to HoughLines need tweaking. have you tried different ones? what parameters?