/// <summary> /// バックプロジェクションにより肌色領域を求める /// </summary> /// <param name="imgSrc"></param> /// <param name="hsvPlanes"></param> /// <param name="imgRender"></param> private void RetrieveFleshRegion(IplImage imgSrc, IplImage[] hsvPlanes, IplImage imgDst) { int[] histSize = new int[] {30, 32}; float[] hRanges = {0.0f, 20f}; float[] sRanges = {50f, 255f}; float[][] ranges = {hRanges, sRanges}; imgDst.Zero(); using (CvHistogram hist = new CvHistogram(histSize, HistogramFormat.Array, ranges, true)) { hist.Calc(hsvPlanes, false, null); float minValue, maxValue; hist.GetMinMaxValue(out minValue, out maxValue); hist.Normalize(imgSrc.Width * imgSrc.Height * 255 / maxValue); hist.CalcBackProject(hsvPlanes, imgDst); } }
// Takes an image and calculates its histogram for one channel. // Color images have 3 channels (4 if you count alpha?) // Webcam captures them in (R)ed, (G)reen, (B)lue. // Convert to (H)ue, (S)aturation (V)alue to get better separation for thresholding CvHistogram CalculateOneChannelHistogram(CvMat _image, int channelNum, float channelMax) { // Hue, Saturation, Value or HSV is a color model that describes colors (hue or tint) // in terms of their shade (saturation or amount of gray) // and their brightness (value or luminance). // For HSV, Hue range is [0,179], Saturation range is [0,255] and Value range is [0,255] if (channelNum > imColorChannels) Debug.LogError("Desired channel number " + channelNum + " is out of range."); float channelMin = 0; float[] channelRanges = new float[2] { channelMin, channelMax }; float[][] ranges = { channelRanges }; // Note: You don't need to use all 3 channels for the histogram. int channelBins = 32; // Number of bins in the Hue histogram (more bins = narrower bins) // Number of bins per histogram channel // If we use all 3 channels (H, S, V) then the histogram will have 3 dimensions. int[] hist_size = new int[] { channelBins }; CvHistogram hist = new CvHistogram(hist_size, HistogramFormat.Array, ranges, true); using (CvMat _imageHSV = ConvertToHSV(_image)) // Convert the image to HSV // We could keep the image in B, G, R, A if we wanted to. // Just split the channels into B, G, R planes using (CvMat imgChannel = new CvMat(_imageHSV.Rows, _imageHSV.Cols, MonoColorMatrix)) { // Break image into H, S, V planes // If the image were BGR, then it would split into B, G, R planes respectively switch (channelNum) { case 0: _imageHSV.CvtPixToPlane(imgChannel, null, null, null); // Cv.Split also does this break; case 1: _imageHSV.CvtPixToPlane(null, imgChannel, null, null); // Cv.Split also does this break; case 2: _imageHSV.CvtPixToPlane(null, null, imgChannel, null); // Cv.Split also does this break; default: Debug.LogError("Channel is out of range"); _imageHSV.CvtPixToPlane(imgChannel, null, null, null); // Cv.Split also does this break; } hist.Calc(Cv.GetImage(imgChannel), false, null); // Call hist function (no accumulatation, no mask) } return hist; // Return the histogram }
// Takes an image and calculates its histogram in HSV color space // Color images have 3 channels (4 if you count alpha?) // Webcam captures them in (R)ed, (G)reen, (B)lue. // Convert to (H)ue, (S)aturation (V)alue to get better separation for thresholding CvHistogram CalculateHSVHistogram(CvMat _image) { // Hue, Saturation, Value or HSV is a color model that describes colors (hue or tint) // in terms of their shade (saturation or amount of gray) // and their brightness (value or luminance). // For HSV, Hue range is [0,179], Saturation range is [0,255] and Value range is [0,255] // hue varies from 0 to 179, see cvtColor float hueMin = 0, hueMax = 179; float[] hueRanges = new float[2] { hueMin, hueMax }; // saturation varies from 0 (black-gray-white) to // 255 (pure spectrum color) float satMin = 0, satMax = 255; float[] saturationRanges = new float[2] { satMin, satMax }; float valMin = 0, valMax = 255; float[] valueRanges = new float[2] { valMin, valMax }; float[][] ranges = { hueRanges, saturationRanges, valueRanges }; // Note: You don't need to use all 3 channels for the histogram. int hueBins = 32; // Number of bins in the Hue histogram (more bins = narrower bins) int satBins = 32; // Number of bins in the Saturation histogram (more bins = narrower bins) int valueBins = 8; // Number of bins in the Value histogram (more bins = narrower bins) float maxValue = 0, minValue = 0; // Minimum and maximum value of calculated histogram // Number of bins per histogram channel // If we use all 3 channels (H, S, V) then the histogram will have 3 dimensions. int[] hist_size = new int[] { hueBins, satBins, valueBins }; CvHistogram hist = new CvHistogram(hist_size, HistogramFormat.Array, ranges, true); using (CvMat _imageHSV = ConvertToHSV(_image)) // Convert the image to HSV // We could keep the image in B, G, R, A if we wanted to. // Just split the channels into B, G, R planes using (CvMat imgH = new CvMat(_image.Rows, _image.Cols, MonoColorMatrix)) using (CvMat imgS = new CvMat(_image.Rows, _image.Cols, MonoColorMatrix)) using (CvMat imgV = new CvMat(_image.Rows, _image.Cols, MonoColorMatrix)) { // Break image into H, S, V planes // If the image were RGB, then it would split into R, G, B planes respectively _imageHSV.CvtPixToPlane(imgH, imgS, imgV, null); // Cv.Split also does this // Store HSV planes as an IplImage array to pass to openCV's hist function IplImage[] hsvPlanes = { Cv.GetImage(imgH), Cv.GetImage(imgS), Cv.GetImage(imgV) }; hist.Calc(hsvPlanes, false, null); // Call hist function (no accumulatation, no mask) // Do we need to normalize?? hist.GetMinMaxValue(out minValue, out maxValue); // Scale the histogram to unity height hist.Normalize(_imageHSV.Width * _imageHSV.Height * hist.Dim * hueMax / maxValue); } return hist; // Return the histogram }
/// <summary> /// ヒストグラムの計算 /// </summary> /// <param name="img"></param> /// <param name="hist"></param> private static void CalcHist(IplImage img, CvHistogram hist) { hist.Calc(img); float minValue, maxValue; hist.GetMinMaxValue(out minValue, out maxValue); Cv.Scale(hist.Bins, hist.Bins, ((double)img.Height) / maxValue, 0); }