/// <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); }
/// <summary> /// Gets flesh regions by histogram back projection /// </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); } }
/// <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); } }
// Creates an image from a 2D Histogram (x axis = Hue, y axis = Saturation) void DrawHSHistogram(CvHistogram hist) { // Get the maximum and minimum values from the histogram float minValue, maxValue; hist.GetMinMaxValue(out minValue, out maxValue); int xBins = hist.Bins.GetDimSize(0); // Number of hue bins (x axis) int yBins = hist.Bins.GetDimSize(1); // Number of saturation bins (y axis) // Create an image to visualize the histogram int scaleHeight = 5, scaleWidth = 5; CvMat hist_img = new CvMat(yBins * scaleHeight, xBins * scaleWidth, TriColorMatrix); hist_img.Zero(); // Set all the pixels to black double binVal; int _intensity; for (int h = 0; h < xBins; h++) { for (int s = 0; s < yBins; s++) { binVal = Cv.QueryHistValue_2D(hist, h, s); _intensity = Cv.Round(binVal / maxValue * 255); // 0 to 255 // Draw a rectangle (h, s) to (h+1, s+1) (scaled by window size) // The pixel value is the color of the histogram value at bin (h, s) hist_img.Rectangle(Cv.Point(h * scaleWidth, s * scaleHeight), Cv.Point((h + 1) * scaleWidth - 1, (s + 1) * scaleHeight - 1), Cv.RGB(_intensity, _intensity, _intensity), Cv.FILLED); } } Cv.ShowImage("HS Histogram", hist_img); }
public IplImage BinarizerMethod_Hist(IplImage src) { bina = new IplImage(src.Size, BitDepth.U8, 1); gray = this.GrayScale(src); int area = 200; int num = 0; int row = (src.Width % area == 0) ? (int)(src.Width / area) : (int)(src.Width / area + 1); int col = (src.Height % area == 0) ? (int)(src.Height / area) : (int)(src.Height / area + 1); int count = row * col; float[] data = new float[count]; IplImage[] piece = new IplImage[count]; CvRect[] piece_roi = new CvRect[count]; for (int x = 0; x < src.Width; x = x + area) { for (int y = 0; y < src.Height; y = y + area) { CvRect roi = new CvRect { X = x, Y = y, Width = area, Height = area }; if (roi.X + roi.Width > src.Width) { roi.Width = area - ((roi.X + roi.Width) - src.Width); } if (roi.Y + roi.Height > src.Height) { roi.Height = area - ((roi.Y + roi.Height) - src.Height); } gray.SetROI(roi); piece[num] = new IplImage(gray.ROI.Size, BitDepth.U8, 1); Cv.Copy(gray, piece[num]); gray.ResetROI(); //히스토그램 계산// int[] size = { area }; CvHistogram hist = new CvHistogram(size, HistogramFormat.Array); Cv.CalcHist(piece[num], hist); float minValue, maxValue; hist.GetMinMaxValue(out minValue, out maxValue); int highlevel = 0; for (int i = 0; i < area; i++) { if (maxValue == hist.Bins[i].Val0) { highlevel = i; } } piece_roi[num] = roi; data[num] = highlevel; num++; } } CvMat kernel = new CvMat(row, col, MatrixType.F32C1, data); Cv.Normalize(kernel, kernel, 255, 0, NormType.C); for (int r = 0; r < count; r++) { Cv.Threshold(piece[r], piece[r], kernel[r], 255, ThresholdType.Otsu); Cv.SetImageROI(bina, piece_roi[r]); Cv.Copy(piece[r], bina); bina.ResetROI(); } //37강 - 윈도우 창// CvWindow win = new CvWindow("window", WindowMode.StretchImage, src); win.Resize(640, 480); win.Move(100, 0); win.ShowImage(piece[0]); win.Close(); new CvWindow(piece[0]).Move(0, 0); new CvWindow(piece[1]).Move(0, 200); new CvWindow(piece[2]).Move(0, 400); //37강 - 윈도우 창// return(bina); }
// 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 }
// Creates an image from a 1D Histogram void Draw1DHistogram(CvMat _image) { float channelMax = 255; CvHistogram hist1 = CalculateOneChannelHistogram(_image, 0, channelMax); CvHistogram hist2 = CalculateOneChannelHistogram(_image, 1, channelMax); CvHistogram hist3 = CalculateOneChannelHistogram(_image, 2, channelMax); // Get the maximum and minimum values from the histogram float minValue, maxValue; hist1.GetMinMaxValue(out minValue, out maxValue); int hBins = hist1.Bins.GetDimSize(0); // Number of bins // Create an image to visualize the histogram int scaleWidth = 3, scaleHeight = 1; int histWidth = hBins * imColorChannels * scaleWidth, histHeight = Mathf.FloorToInt(channelMax * scaleHeight); CvMat hist_img = new CvMat(histHeight, histWidth, TriColorMatrix); hist_img.Zero(); // Set all the pixels to black double binVal; int _intensity; for (int h = 0; h < hBins; h++) { // Draw Channel 1 binVal = Cv.QueryHistValue_1D(hist1, h); _intensity = Cv.Round(binVal / maxValue * channelMax) * scaleHeight; // 0 to channelMax // Draw a rectangle (h, s) to (h+1, s+1) (scaled by window size) // The pixel value is the color of the histogram value at bin (h, s) hist_img.Rectangle(Cv.Point(h * imColorChannels * scaleWidth, histHeight), Cv.Point(h * imColorChannels * scaleWidth + 1, histHeight - _intensity), CvColor.Red, Cv.FILLED); // Draw Channel 2 binVal = Cv.QueryHistValue_1D(hist2, h); _intensity = Cv.Round(binVal / maxValue * channelMax) * scaleHeight; // 0 to channelMax // Draw a rectangle (h, s) to (h+1, s+1) (scaled by window size) // The pixel value is the color of the histogram value at bin (h, s) hist_img.Rectangle(Cv.Point(h * imColorChannels * scaleWidth + 2, histHeight * scaleHeight), Cv.Point(h * imColorChannels * scaleWidth + 3, histHeight * scaleHeight - _intensity), CvColor.Blue, Cv.FILLED); // Draw Channel 3 binVal = Cv.QueryHistValue_1D(hist3, h); _intensity = Cv.Round(binVal / maxValue * channelMax) * scaleHeight; // 0 to channelMax // Draw a rectangle (h, s) to (h+1, s+1) (scaled by window size) // The pixel value is the color of the histogram value at bin (h, s) hist_img.Rectangle(Cv.Point(h * imColorChannels * scaleWidth + 4, histHeight * scaleHeight), Cv.Point(h * imColorChannels * scaleWidth + 5, histHeight * scaleHeight - _intensity), CvColor.Green, Cv.FILLED); } Cv.ShowImage("Histogram", hist_img); }