Search code examples
python-3.xnumpyopencvpython-mss

Error feeding numpy array d.type uint8 into adaptivethreshold function


I'm trying to feed a numpy array into the Process_img (adaptivethreshold) function. The numpy array has a data type of uint8 and 3 dimensions, which should be accepted by the function.

I am getting the following error message. I've tried converting it to grayscale but doesn't seem to work and i've tried numpy.ndarray.flatten (1 dimension), which gets it functioning but doesn't display it back correctly.

I end up getting a long gray bar. I'm not sure of what else i should do. Any help is appreciated.

error: OpenCV(3.4.4) C:\projects\opencv-python\opencv\modules\imgproc\src\thresh.cpp:1524: error: (-215:Assertion failed) src.type() == CV_8UC1 in function 'cv::adaptiveThreshold'

import time
import cv2
import mss
import numpy

# Attempts to change the image to black and white relative to a general area
def process_img(image):
    processed_img = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
    return processed_img

while (True):
    last_time = time.time()

    # Takes a snapshot of the screen location
    with mss.mss() as sct:
        monitor = {"top": 40, "left": 0, "width": 960, "height": 540}  

    # Converts the snapshot to a numpy array    
        npm = numpy.array(sct.grab(monitor))

    # Checks the data type of the numpy array
    print (npm.dtype)

    # Feeds the numpy array into the "process_img" function
    new_screen = process_img(npm)

    # Displays the processed image
    cv2.imshow('Window',new_screen)                  

    #This keeps the screen displayed over time instead of flickering 1ms basically the screen's refresh rate
    if cv2.waitKey(1) & 0xFF == ord('q'):           
        cv2.destroyAllWindows()
        break

Solution

  • Change your process_img() function to convert the image to grayscale:

    def process_img(image):
        image = cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY)
        return cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
    

    Also, you should move with mss.mss() as sct: outside the while to keep performant:

    import time
    
    import cv2
    import mss
    import numpy
    
    
    # Attempts to change the image to black and white relative to a general area
    def process_img(image):
        image = cv2.cvtColor(image, cv2.COLOR_BGRA2GRAY)
        return cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
    
    
    with mss.mss() as sct:
        # Takes a snapshot of the screen location
        monitor = {"top": 40, "left": 0, "width": 960, "height": 540}
    
        while True:
            last_time = time.time()
    
            # Converts the snapshot to a numpy array
            npm = numpy.array(sct.grab(monitor))
    
            # Checks the data type of the numpy array
            print(npm.dtype)
    
            # Feeds the numpy array into the "process_img" function
            new_screen = process_img(npm)
    
            # Displays the processed image
            cv2.imshow("Window", new_screen)
    
            # This keeps the screen displayed over time instead of flickering 1ms basically the screen's refresh rate
            if cv2.waitKey(1) & 0xFF == ord("q"):
                cv2.destroyAllWindows()
                break