Generate Color Histogram around a contoured object

前端 未结 1 1860
再見小時候
再見小時候 2021-01-13 21:12

Hey OpenCV/Emgu gurus,

I have an image that I am generating contour for, see below. I am trying to generate a color histogram based pruning of search space of images

相关标签:
1条回答
  • 2021-01-13 22:01

    Perhaps something like this? Done using the Python bindings, but easy to translate the methods to other bindings...

    #!/usr/local/bin/python
    
    import cv 
    import colorsys
    
    # get orginal image
    orig = cv.LoadImage('car.jpg')
    
    # show orginal 
    cv.ShowImage("orig", orig)
    
    # get mask image
    maskimg = cv.LoadImage('carcontour.jpg')
    
    # split original image into hue and value
    hsv = cv.CreateImage(cv.GetSize(orig),8,3)
    hue = cv.CreateImage(cv.GetSize(orig),8,1)
    val = cv.CreateImage(cv.GetSize(orig),8,1)
    cv.CvtColor(maskimg,hsv,cv.CV_BGR2HSV)
    cv.Split(hsv, hue, None, val, None)
    
    # build mask from val image, select values NOT black
    mask = cv.CreateImage(cv.GetSize(orig),8,1)
    cv.Threshold(val,mask,0,255,cv.CV_THRESH_BINARY)
    
    # show the mask
    cv.ShowImage("mask", mask)
    
    # calculate colour (hue) histgram of only masked area
    hue_bins = 180 
    hue_range = [0,180]
    hist = cv.CreateHist([hue_bins], cv.CV_HIST_ARRAY, [hue_range], 1) 
    cv.CalcHist([hue],hist,0,mask)
    
    # create the colour histogram 
    (_, max_value, _, _) = cv.GetMinMaxHistValue(hist)
    histimg = cv.CreateImage((hue_bins*2, 200), 8, 3) 
    for h in range(hue_bins):
      bin_val = cv.QueryHistValue_1D(hist,h)
      norm_val = cv.Round((bin_val/max_value)*200)
      rgb_val = colorsys.hsv_to_rgb(float(h)/180.0,1.0,1.0) 
      cv.Rectangle(histimg,(h*2,0),
                    ((h+1)*2-1, norm_val),
                    cv.RGB(rgb_val[0]*255,rgb_val[1]*255,rgb_val[2]*255),
                    cv.CV_FILLED)
    cv.ShowImage("hist",histimg)
    
    # wait for key press
    cv.WaitKey(-1)
    

    This is a little bit clunky finding the mask - I wonder perhaps due to JPEG compression artefacts in the image... If you had the original contour it is easy enough to "render" this to a mask instead.

    mask

    The example histogram rendering function is also a wee bit basic - but I think it shows the idea (and how the car is predominately red!). Note how OpenCV's interpretation of Hue ranges only from [0-180] degrees.

    histogram

    EDIT: if you want to use the mask to count colours in the original image - edit as so from line 15 downwards:

    # split original image into hue
    hsv = cv.CreateImage(cv.GetSize(orig),8,3)
    hue = cv.CreateImage(cv.GetSize(orig),8,1)
    cv.CvtColor(orig,hsv,cv.CV_BGR2HSV)
    cv.Split(hsv, hue, None, None, None)
    
    # split mask image into val
    val = cv.CreateImage(cv.GetSize(orig),8,1)
    cv.CvtColor(maskimg,hsv,cv.CV_BGR2HSV)
    cv.Split(hsv, None, None, val, None)
    

    (I think this is more what was intended, as the mask is then derived separately and applied to a completely different image. The histogram is roughly the same in both cases...)

    0 讨论(0)
提交回复
热议问题