I'm working on a school project where I have to make a robot move parallel to a wall and stop when it sees a big red square. For this I have the picamera module and the openCV library. I have working code but the camera takes too long to take a picture (3-4 seconds every time). The analyzing is done in a few milliseconds but I need to take pictures faster. The working code is this:
@staticmethod
def detect_red():
# saving the picture to an in-program stream rather than a file
stream = io.BytesIO()
# to speed things up, lower the resolution of the camera
camera_width = 320
camera_height = 240
#scale_down = 6
red = False
with picamera.PiCamera() as camera:
camera.resolution = (camera_width, camera_height)
# capture into stream
camera.capture(stream, format='jpeg')
# convert image into numpy array
data = np.fromstring(stream.getvalue(), dtype=np.uint8)
# turn the array into a cv2 image
img = cv2.imdecode(data, 1)
# Resizing the image, blur the image and convert it to HSV values for better recognition
# img = cv2.resize(img, (len(img[0]) / scale_down, len(img) / scale_down))
# img = cv2.GaussianBlur(img, (5,5), 0)
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
#Defining the red color range and calculating if these values lie in the range
red_lower = np.array([0, 150, 0], np.uint8)
red_upper = np.array([5, 255, 255], np.uint8)
red_binary = cv2.inRange(img, red_lower, red_upper)
# Dilates the red space, making it larger
dilation = np.ones((15, 15), "uint8")
red_binary = cv2.dilate(red_binary, dilation)
contours, _ = cv2.findContours(red_binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
if not contours == []:
if not red:
red = True
print "Red surface detected!"
else:
print "No red surface detected."
return red
Now I've been trying to get a faster method using capture_continuous and I based my code on: take images in a short time using the Raspberry Pi camera module
def outputs(self):
stream = io.BytesIO()
for i in range(40):
red = False
data = np.fromstring(stream.getvalue(), dtype=np.uint8)
img = cv2.imdecode(data, 1)
print "a"
img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
red_lower = np.array([0, 150, 0], np.uint8)
red_upper = np.array([5, 255, 255], np.uint8)
red_binary = cv2.inRange(img, red_lower, red_upper)
dilation = np.ones((15, 15), "uint8")
red_binary = cv2.dilate(red_binary, dilation)
contours, _ = cv2.findContours(red_binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
if not contours == []:
if not red:
red = True
print "Red surface detected!"
else:
print "No red surface detected."
stream.seek(0)
stream.truncate()
def video_red(self):
with picamera.PiCamera() as camera:
camera.resolution = (320,240)
camera.framerate = 5
camera.start_preview()
time.sleep(2)
camera.capture_continuous(self.outputs(), 'jpeg', use_video_port=True)
This is the new code but I keep getting openCV Error: Assertion failed (scn == 3 || scn == 4) in the cv2.cvtColor method. How can I fix this? I'm also not sure if what I'm doing with the stream is correct. Any help would be appreciated.