Reputation: 321
I'm trying to get pixel values within contours. I've followed along with answers to similar questions but my results are off.
This block of code finds contours for an image and then iterates through them to find the contour containing the largest area. I added the ending if statement that tries to get the RGB value of the code if it is during daylight hours. The original image (video frame) is passed to a function I wrote (grab_rgb)
, along with the contour.
thresh = cv2.dilate(thresh, None, iterations=2)
(_, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# look for motion
motion_found = False
biggest_area = 0
# examine the contours, looking for the largest one
for c in cnts:
(x, y, w, h) = cv2.boundingRect(c)
# get an approximate area of the contour
found_area = w * h
# find the largest bounding rectangle
if (found_area > MIN_AREA) and (found_area > biggest_area):
biggest_area = found_area
motion_found = True
if not is_nighttime():
rgb = grab_rgb(image, c)
else:
rgb = 'nighttime'
This is the function I wrote:
def grab_rgb(image, c):
pixels = []
# TODO: Convert to real code
# Detect pixel values (RGB)
mask = np.zeros_like(image)
cv2.drawContours(mask, c, -1, color=255, thickness=-1)
points = np.where(mask == 255)
for point in points:
pixel = (image[point[1], point[0]])
pixel = pixel.tolist()
pixels.append(pixel)
pixels = [tuple(l) for l in pixels]
car_color = (pixels[1])
r = car_color[0]
g = car_color[1]
b = car_color[2]
pixel_string = '{0},{1},{2}'.format(r, g, b)
return pixel_string
The code runs, but returns only three RGB values, with only the second value containing anything meaningful (values 0 and 2 are [0,0,0],[0,0,0]. There should definitely be more than three pixels within the contours, so I'm not sure where I went wrong.
EDIT: I realized it might be helpful to include what is actually being stored in the variables.
mask:
[[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
[[ 0 0 0]
[255 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
...,
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]
[[ 0 0 0]
[ 0 0 0]
[ 0 0 0]
...,
[ 0 0 0]
[ 0 0 0]
[ 0 0 0]]]
points:
(array([ 1, 1, 3, 5, 10, 11, 11, 12, 12, 13, 13, 14, 14], dtype=int32), array([ 1, 22, 22, 24, 24, 21, 23, 16, 20, 9, 15, 1, 8], dtype=int32), array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], dtype=int32))
pixel:
[0, 0, 0] [136, 89, 96] [0, 0, 0]
pixels:
[(0, 0, 0), (136, 89, 96), (0, 0, 0)]
car_color:
(136, 89, 96)
Upvotes: 1
Views: 3302
Reputation: 66
It seems like what you've asked the code to return is the RGB value of just the second point in the pixel values list (called 'pixels' here ) of the points in every contour passed to grab_rgb, with
car_color = (pixels[1])
r = car_color[0] g = car_color[1] b = car_color[2]
So the output should mean that your image has atleast three detected contours satisfying your area constraints, and that the RGB values of the second point in the contours' point lists are what you mentioned([0,0,0],[x,y,z] and [0,0,0]).
Upvotes: 2