pythonopencvimage-processinghistogramback-projection

OpenCv RGB Histogram Back-projection not working as expected


I use backprojection to locate a person in an image knowing the person's histogram. The issue is that it is not working on skin or on clear clothes. Here is what I get : Back-projection result

Here is the code I use to compute the BGR histogram of the region of interest :

channels=[0,1,2]
histSize = [8,8,8]
ranges=[0,256, 0,256, 0,256]

#image is in BGR color
bgr_split = cv2.split(roi_img)

#Compute image bgr histogram
hist = cv2.calcHist(bgr_split, channels, mask, histSize, ranges)
cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)

The histogram I get is consistant with the person's colors, but when I apply a backprojection on the image containing the person, only the dark regions of the person get non zero values as show in Back-projection result.

I tested the backprojection of my histogram on one pixel and I don't understand the result eiter. I get this :

>> hist[2,2,1]
83.539368
>> pix_img = np.uint8(np.array([[[66,66,34]]]))
>> cv2.calcBackProject([pix_img],channels,hist,ranges,1)
array([[0]], dtype=uint8)

The pixel (b=66, g=66, r=34) should correspond to the histogram bin [2,2,1] since histSize = [8,8,8], yet the backprojection returns 0 instead of 141.

Any idea on what I am doing wrong?


Solution

  • After some tests, it looks like the backprojection function applied on the pixel [b,v,r] gives the backprojection on the pixel [b,v,0], the third channel's value is ignored. I guess it is a bug from opencv and I am going to report it.

    I bypassed the issue by not using this function and replacing it by:

    b,g,r=cv2.split(img/(256/ql))
    B = np.uint8(hist[b.ravel(),g.ravel(), r.ravel()])
    B = B.reshape(img.shape[:2])
    ret, B = cv2.threshold(B,10,255,cv2.THRESH_BINARY)