2

We are currently integrating two codes: 1. mss Image grab for screen recording 2. opencv color tracker

We encountered this error:

File "C:/Users/John Wong/Desktop/Test2.py", line 28, in <module>
_, img = cap.read()

AttributeError: 'NoneType' object has no attribute 'read'

We would like to use the screen grab as our input for the color tracking codes. What will happen is that while the codes for screen capturing is taking place, the codes for color tracking will take effect simultaneously on the screen that is captured.

We do not know what is wrong with our codes, here is the script below:

import cv2
import numpy as np
import time
import mss
import numpy


with mss.mss() as sct:
    # Part of the screen to capture
    monitor = {'top': 80, 'left': 20, 'width': 800, 'height': 770}
    while 'Screen capturing':
        last_time = time.time()

        # Get raw pixels from the screen, save it to a Numpy array
        img = numpy.array(sct.grab(monitor))


        cap = cv2.imshow('OpenCV/Numpy normal', img)

        while(True):
            _, img = cap.read()
            hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

            red_lower = np.array([170,87,97],np.uint8)
            red_upper = np.array([180,255,255],np.uint8)

            blue_lower = np.array([23,59,119],np.uint8)
            blue_upper = np.array([54,255,255],np.uint8)

            yellow_lower = np.array([0,50,80],np.uint8)
            yellow_upper = np.array([20,255,255],np.uint8)

            red = cv2.inRange(hsv, red_lower, red_upper)
            blue = cv2.inRange(hsv, blue_lower, blue_upper)
            yellow = cv2.inRange(hsv, yellow_lower, yellow_upper)

            kernal = np.ones((5,5), "uint8")

            red = cv2.dilate(red,kernal)
            res = cv2.bitwise_and(img, img, mask = red)

            blue = cv2.dilate(blue, kernal)
            res1 = cv2.bitwise_and(img, img, mask = blue)

            yellow = cv2.dilate(yellow, kernal)
            res2 = cv2.bitwise_and(img, img, mask = yellow)

            (_,contours, heirarchy) = cv2.findContours(red,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

            for pic, contour in enumerate(contours):
                area = cv2.contourArea(contour)
                if(area>300):
                    x,y,w,h = cv2.boundingRect(contour)
                    img = cv2.rectangle(img,(x,y),(x+w,y+h),(61,26,76),2)
                    cv2.putText(img,"PRIORITY",(x,y),cv2.FONT_HERSHEY_SIMPLEX,0.7,(61,26,76))

            (_,contours, heirarchy) = cv2.findContours(blue,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
            for pic, contour in enumerate(contours):
                area = cv2.contourArea(contour)
                if(area>300):
                    x,y,w,h = cv2.boundingRect(contour)
                    img = cv2.rectangle(img,(x,y),(x+w,y+h), (255,0,0),2)
                    cv2.putText(img,"SECOND",(x,y),cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255,0,0))

            (_,contours,heirarchy) = cv2.findContours(yellow,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
            for pic, contour in enumerate(contours):
                area = cv2.contourArea(contour)
                if(area>300):
                    x,y,w,h = cv2.boundingRect(contour)
                    img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,217),2)
                    cv2.putText(img,"ALERT",(x,y),cv2.FONT_HERSHEY_SIMPLEX,1.0, (0,255,217))

            cv2.imshow("Color Tracking", img)

            if cv2.waitKey(10) & 0xFF == ord('q'):
                cap.release()
                cv2.destroyAllWindows()
                break

Thank you in advance! :)

Tiger-222
  • 6,677
  • 3
  • 47
  • 60
Markus
  • 59
  • 6

1 Answers1

1

I don't really understand what is going on in this code, and what you are expecting cap to be, however:

This line here reads the image into img

        img = numpy.array(sct.grab(monitor))

and then you show that image in a window using this line:

        cap = cv2.imshow('OpenCV/Numpy normal', img)

The cap is now a NoneType as shown in your error message (Thanks @DanMašek), so instead of using Cap as the image in the rest of your code use img instead.

while(True):
        # Remove this line: _, img = cap.read()
        # Get raw pixels from the screen, save it to a Numpy array
        img = numpy.array(sct.grab(monitor)) #Update the new image
        hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)

        red_lower = np.array([170,87,97],np.uint8)
        red_upper = np.array([180,255,255],np.uint8)

        blue_lower = np.array([23,59,119],np.uint8)
        blue_upper = np.array([54,255,255],np.uint8)

        yellow_lower = np.array([0,50,80],np.uint8)
        yellow_upper = np.array([20,255,255],np.uint8)

        red = cv2.inRange(hsv, red_lower, red_upper)
        blue = cv2.inRange(hsv, blue_lower, blue_upper)
        yellow = cv2.inRange(hsv, yellow_lower, yellow_upper)

        cv2.imshow('Processed', img)
        cv2.waitKey(1)
GPPK
  • 6,546
  • 4
  • 32
  • 57
  • it worked but, we aim to color track the screen and not just a captured image of it. After removing the line: _, img = cap.read() it only displays the image of the screen after running the program. with mss.mss() as sct: monitor = {'top': 80, 'left': 20, 'width': 800, 'height': 770} while 'Screen capturing': last_time = time.time() img = numpy.array(sct.grab(monitor)) cv2.imshow('OpenCV/Numpy normal', img) – Markus Mar 29 '18 at 13:30
  • Ah yes, because you hit the while(true) loop and no longer update your image. You need to read in the screen capture each time. See my update – GPPK Mar 29 '18 at 13:32
  • "It's likely that cap is now a bool" -- it's a `None`, hence the error message about `NoneType` ;) – Dan Mašek Mar 29 '18 at 13:40
  • 1
    @DanMašek Fair enough, I have zero python experience and no test environment for it! hence the fairly wishy washy start to the answer... lol – GPPK Mar 29 '18 at 13:45