Generate colored histogram around contour
Hey OpenCV / Emgu guru,
I have an image that I am creating an outline for, see below. I am trying to create a color histogram based clipping of an image search space for search. How can I get a mask around just the selected outline of an object and block the rest. So I have 2 questions:
How do I "invert" an image outside the outline? FloodFill invert, don't? I am confused with all the options in OpenCV.
Second, how do I create a 1-dimensional color histogram from the outline of an object in this case a red car to exclude the black background and generate only a color histogram that includes the car.
How can I do this in OpenCV (preferably in Emgu / C # code)?
source to share
Perhaps something like this? Done using Python bindings, but easy to translate methods into 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*255,rgb_val*255,rgb_val*255), cv.CV_FILLED) cv.ShowImage("hist",histimg) # wait for key press cv.WaitKey(-1)
This is a bit awkward mask detection - interesting, perhaps because of the JPEG compression artifacts in the image ... If you had the original path, simply "render" that mask instead.
An example of a histogram rendering function is also basic, but I think it shows the idea (and how the car is predominantly red!). Note that OpenCV's interpretation of Hue only varies from [0-180] degrees.
EDIT: if you want to use a mask to count colors in the original image - edit it like this from line 15 down:
# 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 than what was intended, since then the mask is output separately and applied to a completely different image. The histogram is about the same in both cases ...)
source to share