pythonopencvhoughlinesp

OpenCV Python: Detecting lines only in ROI


I'd like to detect lines inside a region of interest. My output image should display the original image and the detected lines in the selected ROI. So far it has not been a problem to find lines in the original image or select a ROI but finding lines only inside the ROI did not work. My MWE reads an image, converts it to grayscale and lets me select a ROI but gives an error when HoughLinesP wants to read roi.

import cv2
import numpy as np

img = cv2.imread('example.jpg',1)
gray = cv2.cvtColor(img ,cv2.COLOR_BGR2GRAY)

# Select ROI
fromCenter = False
roi = cv2.selectROI(gray, fromCenter)

# Crop ROI
roi = img[int(roi[1]):int(roi[1]+roi[3]), int(roi[0]):int(roi[0]+roi[2])]

# Find lines
minLineLength = 100
maxLineGap = 30
lines = cv2.HoughLinesP(roi,1,np.pi/180,100,minLineLength,maxLineGap)
for x in range(0, len(lines)):
    for x1,y1,x2,y2 in lines[x]:
        cv2.line(img,(x1,y1),(x2,y2),(237,149,100),2)

cv2.imshow('Image',img)
cv2.waitKey(0) & 0xFF

cv2.destroyAllWindows()

The console shows:

lines = cv2.HoughLinesP(roi,1,np.pi/180,100,minLineLength,maxLineGap)

error: OpenCV(3.4.1) C:\Miniconda3\conda-bld\opencv-suite_1533128839831\work\modules\imgproc\src\hough.cpp:441: error: (-215) image.type() == (((0) & ((1 << 3) - 1)) + (((1)-1) << 3)) in function cv::HoughLinesProbabilistic

My assumption is that roi does not have the correct format. I am using Python 3.6 with Spyder 3.2.8. Thanks for any help!


Solution

  • The function cv2.HoughLinesP is expecting a single-channel image, so the cropped region could be taken from the gray image and that would remove the error:

    # Crop the image
    roi = list(map(int, roi)) # Convert to int for simplicity
    cropped = gray[roi[1]:roi[1]+roi[3], roi[0]:roi[0]+roi[2]]
    

    Note that I'm changing the output name from roi to cropped, and that's because you're going to still need the roi box. The points x1, x2, y1, and y2 are pixel positions in the cropped image, not the full image. To get the images drawn correctly, you can just add the upper left corner pixel position from roi. Here's the for loop with relevant edits:

    # Find lines
    minLineLength = 100
    maxLineGap = 30
    lines = cv2.HoughLinesP(cropped,1,np.pi/180,100,minLineLength,maxLineGap)
    for x in range(0, len(lines)):
        for x1,y1,x2,y2 in lines[x]:
            cv2.line(img,(x1+roi[0],y1+roi[1]),(x2+roi[0],y2+roi[1]),(237,149,100),2)