1

I'm attempting to find vertical lines in a video. Python 2.7 and OpenCV 3. I am using background subtraction and then applying the Canny Edge Detection filter. I've been able to apply the HoughLinesP method to a single image but need to expand this to a video.

I'm receiving this error when running a basic set of code (which I believe corresponds to the lines (30-33) below:

Traceback (most recent call last):
File "test3.py", line 33, in <module>
print(hlines.shape)
AttributeError: 'NoneType' object has no attribute 'shape'  

What's strange is that if Iadjust the code so that background subtraction is not applied (comment line 26 and change line 28 so that it's referring to 'frame' instead of 'img_sub'), everything works just fine. What am I missing?
I can output a background subtracted video stream just fine and it works as expected.
I can output/ print(hlines) just fine.
Example terminal output of 'hlines'

[[470 109 470 109]]

[[337 259 337 259]]

[[330 267 330 267]]

[[338 324 338 324]]

[[338 289 338 289]]]

But, as soon as I try to use the hlines.shape attribute, things go wonky.

import cv2
import numpy as np
import imutils 

np.set_printoptions(threshold=np.inf) #to print entire array, no truncation

LOWER_BOUND = 55   #cv2.threshold()
UPPER_BOUND = 255  #cv2.threshold()

CANNY_LOWER_BOUND = 10  #cv2.Canny()
CANNY_UPPER_BOUND = 250 #cv2.Canny()

MIN_LINE_LENGTH = 2  #HoughLinesP()
MAX_LINE_GAP = 100     #HoughLinesP() 
HOUGH_THETA = np.pi/180 #HoughLinesP() angle resolution of the accumulator, radians
HOUGH_THRESHOLD = 25 #HoughLinesP() 
HOUGH_RHO = 1         #HoughLinesP() rho, Distance resolution of the accumulator, pixels

#background subtraction parameter
bkgnd = cv2.bgsegm.createBackgroundSubtractorMOG()
camera =cv2.VideoCapture('/home/odroid/Desktop/python_scripts/test/test_images/Edited_Foam_Dispense_Short.mp4')

while(True):
(grabbed, frame) = camera.read()

img_sub = bkgnd.apply(frame)#, learningRate = 0.001)

canny_threshold = cv2.Canny(img_sub, CANNY_LOWER_BOUND, CANNY_UPPER_BOUND)  

hlines = cv2.HoughLinesP(canny_threshold, HOUGH_RHO, HOUGH_THETA, MIN_LINE_LENGTH, MAX_LINE_GAP)

print(hlines)
print(hlines.shape)

#a,b,c = hlines.shape

#for k in range(a):
    #print(hlines.shape)
    #break
    #cv2.line(frame, (hlines[k][0][0], hlines[k][0][1]), (hlines[k][0][2], hlines[k][0][3]), (0,255,0), 3, cv2.LINE_AA)
#   print("getting hlines")
#   break

cv2.imshow('canny_threshold', canny_threshold)
cv2.imshow("frame", frame)

if cv2.waitKey(1) & 0xFF == ord('q'):
    break

camera.release()
cv2.destroyAllWindows()  

Any suggestions would be appreciated.

EDIT:
@ivan_pozdeev pointed me to this question.

It does look like it applies. But, while trying to follow their solution, I'm getting the following error:

Traceback (most recent call last): File "test3.py", line 37, in for l in hlines: TypeError: 'NoneType' object is not iterable

This is the modified code snippet:

hlines = cv2.HoughLinesP(canny_threshold, HOUGH_RHO, HOUGH_THETA, MIN_LINE_LENGTH, MAX_LINE_GAP)

for l in hlines:
    leftx, boty, rightx, topy = l[0]
    line = Line((leftx, boty), (rightx, topy)) 
    line.draw(frame, (0, 255, 0), 2)

Now, this would kind of makes sense to me if I didn't have data ... but I do have data being returned in hlines. I can print it out using a print(hlines) statement. However, it has a different format than OpenCV 2.4... But, now it has me wondering why it worked in the other question...

EDIT2:
Ah ha! Making progress. Here's the output of the script (print(hlines)) if I only loop it twice ... ie, when run_once = 0 while(run_once<=1) ... run_once = 1+ run_once at the end

None
[[[690 419 693 419]]

[[672 419 679 419]]

[[696 417 701 417]]

[[713 419 714 419]]

[[504 418 504 418]]

[[688 419 688 419]]

[[672 417 679 417]]

[[510 419 511 419]]

[[693 418 693 417]]

[[688 417 688 417]]

[[692 417 692 417]]

[[696 419 699 419]]

[[713 417 714 417]]

[[686 419 686 419]]

[[622 417 622 417]]

[[690 417 690 417]]

[[506 417 506 417]]

[[622 419 623 419]]

[[505 419 505 419]]

[[686 417 687 417]]

[[506 419 506 419]]

[[700 419 701 418]]

[[509 418 509 418]]

[[623 417 623 417]]

[[510 417 511 417]]

[[712 418 712 418]]

[[685 418 685 418]]

[[689 417 689 417]]

[[689 419 689 419]]

[[671 418 671 418]]

[[691 417 691 417]]]

So it looks like the first row of hlines is "None". Which explains the error, I think. However, now I need to figure out how to add an "empty row" to hlines ....

Community
  • 1
  • 1
slow_one
  • 113
  • 1
  • 4
  • 13

1 Answers1

0

Following the link posted above by @ivan_pozdeev and checking for a return type of None fixed the issue.
The HoughLinesP function was returning an empty array on the first frame (returning "None"). This caused errors down the line. Adding in a check for that fixed the issue.

if hlines is None: #in case HoughLinesP fails to return a set of lines
        #make sure that this is the right shape [[ ]] and ***not*** []
        hlines = [[0,0,0,0]]
    else:
        for l in hlines:
            leftx, boty, rightx, topy = l[0]
            cv2.line(frame, (leftx, boty), (rightx, topy), (0, 255, 0), 2)
slow_one
  • 113
  • 1
  • 4
  • 13
  • All that leaves is find out why it's `None`. This possibility is not mentioned in in the documentation. I checked [its source](https://github.com/opencv/opencv/blob/26be2402a3ad6c9eacf7ba7ab2dfb111206fffbb/modules/imgproc/src/hough.cpp#L870) and didn't find any immediately apparent cases. – ivan_pozdeev Apr 28 '17 at 20:55
  • double-checked the link - it's fine. Maybe https://github.com is blocked in your country or something. – ivan_pozdeev May 01 '17 at 18:45
  • might be at work ... i'll fiddle with it. which source were you checking? the HoughLinesP? – slow_one May 01 '17 at 19:27