2

So with my code, I'm analyzing the total number of pixels that are within the threshold of my values. However, it's very slow, and it all comes down to one line of code, basically bottle-necking the entire program. This code is simple, in that it splits the array up into the values so I can count the length, however, it brings the frames per second down from 30 to about 4.

import cv2
import numpy as np
import time
from picamera.array import PiRGBArray
from picamera import PiCamera
import RPi.GPIO as GPIO
from PIL import Image


camera = PiCamera()
camera.resolution = (320,240)
rawCapture= PiRGBArray(camera)


for frame in camera.capture_continuous(rawCapture, format='bgr', use_video_port=True):
    data= frame.array

    lower=np.array([100, %0, 50], dtype='uint8')
    upper= np.array([250, 150, 150], dtype="uint8")

    thresh= cv2.inRange(data, lower, upper)
    data={tuple(item) for item in thresh} # this is the problem line.
    len(data)

    rawCapture.truncate(0)
    FPS=FPS+1
    New_time=time.time()-start
    if New_time> 10:
        print FPS/10, 'fps'
        New_time=0
        start=time.time()
        FPS=0

I feel like half the problem is that it is a loop (python hates loops), but I don't really know how to alter arrays. What's the 'pythonic' way of achieving this?

Davey Boy
  • 79
  • 1
  • 10
  • What exactly do you mean by length? It seems to me that you re trying to find the number of unique rows in your array, is that accurate? – juanpa.arrivillaga Aug 13 '16 at 07:14
  • yes that is correct. – Davey Boy Aug 13 '16 at 07:14
  • I wanted just anything that showed out, but this method appears to be working. If I could get individual pixel that would be brilliant but right now I'm just using what is working. – Davey Boy Aug 13 '16 at 07:15
  • Hmmm. I am unfamiliar with the libary, but if `hresh= cv2.inRange(data, lower, upper)` is an array with values from `data` that are within your range, then you should be able to just use `hresh.shape`, no? I'm still not understanding why they need to be unique. – juanpa.arrivillaga Aug 13 '16 at 07:18
  • @juanpa.arrivillaga Or even `thresh.size` for the total number of pixels – Moses Koledoye Aug 13 '16 at 07:22
  • @MosesKoledoye even better... but notice this code is only looking at one axis. Honestly, I think this question could do with some clarification. I don't think it's just my unfamiliarity with the associated libraries. – juanpa.arrivillaga Aug 13 '16 at 07:22
  • It's a detection program. I don't want the size of the picture itself, nor how many total pixels. Just the pixels that are within the threshold. Those suggestions include pixels that have now been altered to (0, 0, 0). I want to know the pixels that are between the upper and lower values. – Davey Boy Aug 13 '16 at 07:25
  • Try, then, `np.unique(data).size` – juanpa.arrivillaga Aug 13 '16 at 07:26
  • But that will also count pixels with are not within my threshold. – Davey Boy Aug 13 '16 at 07:28
  • 1
    sorry, `np.unique(thresh).size` – juanpa.arrivillaga Aug 13 '16 at 07:29
  • That appears to return a value of one, and it is also an int, so it is impossible to count. I don't exactly know what went one there but yeah... – Davey Boy Aug 13 '16 at 07:32
  • I realize now that you are working with some number of rows, which represent a single pixel, and three columns. Try to follow some of the suggestions here: http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array – juanpa.arrivillaga Aug 13 '16 at 07:33
  • So you are trying to find how many unique rows there are in `thresh`? Try searching for SO questions on `unique rows`. – hpaulj Aug 13 '16 at 07:39
  • @DaveyBoy you want the length of the pixels or the pixels themselves (within the threshold)? – Moses Koledoye Aug 13 '16 at 07:41
  • I think my code would require an additional for loop to be accurate. I do want individual pixels, not rows. Also the method in that question uses arrays that are of integers, which will not work on this type of array. – Davey Boy Aug 13 '16 at 07:42
  • @Moses Koledoye How many pixels in the threshold is the aim. Rows sorta work for detection, but aren't optimal. – Davey Boy Aug 13 '16 at 07:43

1 Answers1

1

I don't want the size of the picture itself, nor how many total pixels. Just the pixels that are within the threshold.

cv2.inRange already does that, so the set comprehension will not be required:

After calling cv2.inRange, a binary mask is returned, where white pixels (255) represent pixels that fall into the upper and lower limit range and black pixels (0) do not.

From the binary mask, the in-range values can be counted with:

thresh = cv2.inRange(data, lower, upper)
within_threshold = (thresh == 255).sum()

To get the pixels themselves, you can index the original data on the in-range binary mask:

data = data[thresh == 255]
Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139