0
votes

I'm trying to obtain the RGB histogram of a zone on a picture. I've already isolated my zone by thresholding the picture (the background is bright, and my isolated zone is dark). I know how to make the color histogram of my entire picture, but not the RGB histogram of just my zone, by using the contour of my zone as a mask in calcHist OpenCV function.

What I actually do is :

#I threshlod my picture to obtain my objects of interest
threshold = threshold3(img, param['thresh_red_low'], param['thresh_red_high'], param['thresh_green_low'], param['thresh_green_high'], param['thresh_blue_low'])

#I find contours of my objects
contours = cv2.findContours(threshold , cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]

#For each of my objects
for indexx, contour in enumerate(contours):

    #If I directly try to put contour as a mask in calcHist, I got an error
    #I convert the contour into a mask
    mask = cv2.drawContours(image_color, contour, -1, (255, 255, 255), 2)

    #I calculate histograms for BGR channel, on ten ranges, from 5 to 256
    b_hist = cv2.calcHist([image_color],[0],mask,[10],[5,256])                        
    g_hist = cv2.calcHist([image_color],[1],mask,[10],[5,256])
    r_hist = cv2.calcHist([image_color],[2],mask,[10],[5,256])

   #Then I save results into a csv

But I got too many values in each of histogram range. For example, my first zone has an area of 6371 px, and its histogram values are :

Number of red pixels per range : 388997,500656,148124,97374,198893,793015,894672,1232693,674721,105807

Number of green pixels per range :
123052,478714,349357,153624,117838,105738,84656,1205018,1356478,1064373

Number of blue pixels per range :
1590057,702532,547988,430238,320658,103876,15366,7629,1527,2645

Which is more like the entire picture histogram than the zone's. What do I don't understand about mask and contour in calcHist function ?

1

1 Answers

0
votes

Sorry for such a late response but this might help somebody else, I hope.

By and large your code is correct only that you may need to add just a line or two and modify one line a bit.

#I threshlod my picture to obtain my objects of interest
threshold = threshold3(img, param['thresh_red_low'], param['thresh_red_high'], param['thresh_green_low'], param['thresh_green_high'], param['thresh_blue_low'])

#I find contours of my objects
contours = cv2.findContours(threshold , cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
#For each of my objects
for indexx, contour in enumerate(contours):
#If I directly try to put contour as a mask in calcHist, I got an error
#I convert the contour into a mask

w, h = img.shape
mask = np.zeros((h, w), dtype="uint8")
cv2.drawContours(mask, contours, indexx, 255, cv2.FILLED)


#I calculate histograms for BGR channel, on ten ranges, from 5 to 256
b_hist = cv2.calcHist([image_color],[0],mask,[10],[5,256])                        
g_hist = cv2.calcHist([image_color],[1],mask,[10],[5,256])
r_hist = cv2.calcHist([image_color],[2],mask,[10],[5,256])

#Then I save results into a csv

This solution assumes that you are interested in everything that's been found inside the contour.