Facing an error in program of image capturing and processing using opencv(cv2) and python
Question: In the following program, it captures and processes image runtime. But I am
facing a lot problems in the code. The first problem is, when camera is
initialized for the first time and if it is unable to detect red colour in
captured frame then it gives following error.

    
    
    Traceback (most recent call last):
      File "/home/mukund/Desktop/Checknewcod/attempone.py", line 23, in <module>
        M=cv2.moments(best_cnt)
    NameError: name 'best_cnt' is not defined
    

Sometimes it gives following error.

    
    
    Traceback (most recent call last):
      File "/home/mukund/Desktop/New logic/GridTestcal1.py", line 287, in <module>
        fun2()
      File "/home/mukund/Desktop/New logic/GridTestcal1.py", line 230, in fun2
        M=cv2.moments(best_cnt)
    UnboundLocalError: local variable 'best_cnt' referenced before assignment
    

The code is as follows.

    
    
    import cv2
    import numpy as np
    capture = cv2.VideoCapture(1)
    num = 0
    while True:           
        flag, img2 = capture.read()
        flag=capture.set(3,640)
        flag=capture.set(4,480)
        cv2.imwrite('pic'+str(num)+'.jpg', img2)
        img1=cv2.imread('pic'+str(num)+'.jpg')
        img=cv2.blur(img1,(3,3))
        ORANGE_MIN=np.array([170,160,60],np.uint8)
        ORANGE_MAX=np.array([180,255,255],np.uint8)
        hsv_img=cv2.cvtColor(img1,cv2.COLOR_BGR2HSV)
        frame_thresh=cv2.inRange(hsv_img,ORANGE_MIN,ORANGE_MAX)
        contours,hierarchy=cv2.findContours(frame_thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
        x_area=0
        for cnt in contours:
            area=cv2.contourArea(cnt)
            if area>x_area:
            x_area=area
            best_cnt=cnt     
        M=cv2.moments(best_cnt)
        cx,cy=int(M['m10']/M['m00']),int(M['m01']/M['m00'])
        cv2.circle(frame_thresh,(cx,cy),5,255,-1)
        cv2.imwrite('pic1'+str(num)+'.jpg',frame_thresh)
        print cx,cy
        if num == 30:
            capture.release()
            break         
        num += 1
    

Is there any efficient way to implement above code such as using video
processing?


Answer: For the error, you should check that the number of returned contours is > 0.
In some cases no coutours are detected so best_cnt is not set so the error is
telling you that you are referencing it before defining that variable.

    
    
    for cnt in contours:
        area=cv2.contourArea(cnt)
        if area>x_area:  # I believe your code is indented wrongly here
            x_area=area
            best_cnt=cnt
    
    if len(cnt) > 0:  # In some cases no coutours are detected so best_cnt is not set.   
        M=cv2.moments(best_cnt)
        cx,cy=int(M['m10']/M['m00']),int(M['m01']/M['m00'])
        cv2.circle(frame_thresh,(cx,cy),5,255,-1)
        cv2.imwrite('pic1'+str(num)+'.jpg',frame_thresh)
        print cx,cy
    
    if num == 30:
        capture.release()
        break         
    num += 1
    

The bulk of the processing time for your code, I believe, should be in reading
and writing the image. If you are getting the frames from a video camera, then
things might be slightly better, especially if its frame rate is high. If you
can choose to write the frames every say `k` images then it might help avoid
dropping frames. Also, it would help if you can narrow down the region of
interest (ROI) and only perform the image processing algorithms such as
cvtColor, inRange, and findContours on it.

Some minor tweaks would be to move the declaration of `ORANGE_MIN/MAX` outside
of the while loop.

