public void createEqualizedHistogram() { float[] range = { 0, 255 }; float[][] ranges = { range }; int histogramSize = 255; float minimumValue, maximumValue = 0; histogramImage = Cv.CreateImage(srcImage.Size, BitDepth.U8, 1); convertionGrayScale(); Cv.EqualizeHist(grayscaleImage, grayscaleImage); CvHistogram histogramR = Cv.CreateHist(new int[] { histogramSize }, HistogramFormat.Array, ranges, true); Cv.CalcHist(grayscaleImage, histogramR); Cv.GetMinMaxHistValue(histogramR, out minimumValue, out maximumValue); Cv.Scale(histogramR.Bins, histogramR.Bins, ((double)histogramImage.Height) / maximumValue, 0); histogramImage.Set(CvColor.White); int bin_red = Cv.Round((double)histogramImage.Width / histogramSize); int r; for (r = 0; r < histogramSize; r++) { histogramImage.Rectangle(new CvPoint(r * bin_red, grayscaleImage.Height), new CvPoint((r + 1) * bin_red, grayscaleImage.Height - Cv.Round(histogramR.Bins[r])), CvColor.Black, -1, LineType.Link8, 0); } Cv.SaveImage("newHistoMode1.jpg", histogramImage); Cv.SaveImage("newHistoMode2.jpg", grayscaleImage); }
/// <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); }
public void DrawHistogram() { //variable declaration float [] range = { 0, 255 }; float[][] ranges = { range }; //defining 2D array int his_size = 256; float min_value, max_value = 0; //call convertgray function ConvertToGray(); //create an inage to hold the histogarm histImage = Cv.CreateImage(image1.Size, BitDepth.U8, 1); //create a histogarm to store information from the image CvHistogram hist = Cv.CreateHist(new int [] { his_size }, HistogramFormat.Array, ranges, true); //rangers ==> starting and ending values of the range //HistogramFormat.Array ==> 2D array //true ==> each scale of the histogarm is eqaully distributed //new int [] { his_size } ==> y axis is given as a dynamic array since the limit is not known/fixed //calculate the histogram and apply to histogram Cv.CalcHist(image1, hist); //grab min and max Cv.GetMinMaxHistValue(hist, out min_value, out max_value); //scale the bin values (gaps) so that thay will fit in the image representation Cv.Scale(hist.Bins, hist.Bins, ((double)histImage.Height) / max_value, 0); //hist.Bins ==> for the source and the destination to be scaled. //((double) histImage.Height) / max_value ==> scale value. //0 ==> to represent a null mask. its a default parameter. //set all histogram values to 255 histImage.Set(CvColor.White); //create a factor for scaling along the width int bin_w = Cv.Round(((double)histImage.Width / his_size)); int i; for (i = 0; i < his_size; i++) { histImage.Rectangle( new CvPoint(i * bin_w, image1.Height), new CvPoint((i + 1) * bin_w, image1.Height - Cv.Round(hist.Bins[i])), CvColor.Black, //line drawn in black -1, //thickness LineType.Link8, //indicated the link type (connected) 0 //shift bit (factional bits in the coordinate) ); } Cv.SaveImage("3.jpg", histImage); }
// OpenCVSharp was so inconsequential with its own copy function that I had to wrap it up and make it into something sensible static public CvHistogram CopyHistogram(CvHistogram source) { int[] sizes = new int[source.Dim]; for (int i = 0; i < source.Bins.Dims; ++i) { sizes[i] = source.Bins.GetDimSize(i); } CvHistogram newHisto = new CvHistogram(sizes, source.Type); source.Copy(newHisto); // NOTE : source is copied INTO newHisto = "CopyTo" return(newHisto); }
public Histogram() { // cvCalcHist // コントラストや明度をいろいろ変えられるサンプル const int histSize = 64; float[] range0 = { 0, 256 }; float[][] ranges = { range0 }; // 画像の読み込み using (IplImage srcImg = new IplImage(Const.ImageLenna, LoadMode.GrayScale)) using (IplImage dstImg = srcImg.Clone()) using (IplImage histImg = new IplImage(new CvSize(400, 400), BitDepth.U8, 1)) using (CvHistogram hist = new CvHistogram(new int[] { histSize }, HistogramFormat.Array, ranges, true)) { using (CvWindow windowImage = new CvWindow("image", WindowMode.AutoSize)) using (CvWindow windowHist = new CvWindow("histogram", WindowMode.AutoSize)) { // トラックバーが動かされた時の処理 CvTrackbar ctBrightness = null; CvTrackbar ctContrast = null; CvTrackbarCallback callback = delegate(int pos) { int brightness = ctBrightness.Pos - 100; int contrast = ctContrast.Pos - 100; // LUTの適用 byte[] lut = CalcLut(contrast, brightness); srcImg.LUT(dstImg, lut); // ヒストグラムの描画 CalcHist(dstImg, hist); DrawHist(histImg, hist, histSize); // ウィンドウに表示 windowImage.ShowImage(dstImg); windowHist.ShowImage(histImg); dstImg.Zero(); histImg.Zero(); }; // トラックバーの作成 // (OpenCVでは現在位置にポインタを渡すことでトラックバーの位置の変化が取得できるが、 // .NETではGCによりポインタが移動してしまうので廃止した。別の方法でうまく取得すべし。) ctBrightness = windowImage.CreateTrackbar("brightness", 100, 200, callback); ctContrast = windowImage.CreateTrackbar("contrast", 100, 200, callback); // 初回描画 callback(0); // キー入力待ち Cv.WaitKey(0); } } }
/// <summary> /// ヒストグラムの描画 /// </summary> /// <param name="img"></param> /// <param name="hist"></param> /// <param name="histSize"></param> private static void DrawHist(IplImage img, CvHistogram hist, int histSize) { img.Set(CvColor.White); int binW = Cv.Round((double)img.Width / histSize); for (int i = 0; i < histSize; i++) { img.Rectangle( new CvPoint(i * binW, img.Height), new CvPoint((i + 1) * binW, img.Height - Cv.Round(hist.Bins[i])), CvColor.Black, -1, LineType.AntiAlias, 0 ); } }
public IplImage BuildHist(IplImage src_tmp) { const int histSize = 64; float[] range0 = { 0, 256 }; float[][] ranges = { range0 }; // 화상의 읽기 using (IplImage srcImg = new IplImage(src_tmp.Size, BitDepth.U8, 1)) using (IplImage dstImg = new IplImage(src_tmp.Size, BitDepth.U8, 1)) using (IplImage histImg = new IplImage(new CvSize(400, 400), BitDepth.U8, 1)) using (CvHistogram hist = new CvHistogram(new int[] { histSize }, HistogramFormat.Array, ranges, true)) { src_tmp.CvtColor(srcImg, ColorConversion.BgrToGray); srcImg.Copy(dstImg); using (CvWindow windowImage = new CvWindow("변환된 이미지", WindowMode.AutoSize)) using (CvWindow windowHist = new CvWindow("히스토그램", WindowMode.AutoSize)) { // 트랙바가 동작되었을 때의 처리 CvTrackbar ctBrightness = null; CvTrackbar ctContrast = null; CvTrackbarCallback callback = delegate(int pos) { int brightness = ctBrightness.Pos - 100; int contrast = ctContrast.Pos - 100; // LUT의 적용 byte[] lut = CalcLut(contrast, brightness); srcImg.LUT(dstImg, lut); // 히스토그램 그리기 CalcHist(dstImg, hist); DrawHist(histImg, hist, histSize); // 윈도우에 표시 DstHist = histImg.Clone(); windowImage.ShowImage(dstImg); windowHist.ShowImage(histImg); dstImg.Zero(); histImg.Zero(); }; // 트랙바의 작성 ctBrightness = windowImage.CreateTrackbar("명도", 100, 200, callback); ctContrast = windowImage.CreateTrackbar("대조", 100, 200, callback); // 첫회 그리기 callback(0); // 키 입력대기 Cv.WaitKey(0); } return(DstHist); } }
/// <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); } }
/// <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); } }
public Histogram() { // cvCalcHist const int histSize = 64; float[] range0 = { 0, 256 }; float[][] ranges = { range0 }; using (IplImage srcImg = new IplImage(FilePath.Image.Lenna, LoadMode.GrayScale)) using (IplImage dstImg = srcImg.Clone()) using (IplImage histImg = new IplImage(new CvSize(400, 400), BitDepth.U8, 1)) using (CvHistogram hist = new CvHistogram(new int[] { histSize }, HistogramFormat.Array, ranges, true)) { using (CvWindow windowImage = new CvWindow("image", WindowMode.AutoSize)) using (CvWindow windowHist = new CvWindow("histogram", WindowMode.AutoSize)) { CvTrackbar ctBrightness = null; CvTrackbar ctContrast = null; CvTrackbarCallback callback = delegate(int pos) { int brightness = ctBrightness.Pos - 100; int contrast = ctContrast.Pos - 100; // perform LUT byte[] lut = CalcLut(contrast, brightness); srcImg.LUT(dstImg, lut); // draws histogram CalcHist(dstImg, hist); DrawHist(histImg, hist, histSize); windowImage.ShowImage(dstImg); windowHist.ShowImage(histImg); dstImg.Zero(); histImg.Zero(); }; ctBrightness = windowImage.CreateTrackbar("brightness", 100, 200, callback); ctContrast = windowImage.CreateTrackbar("contrast", 100, 200, callback); // initial action callback(0); Cv.WaitKey(0); } } }
void TransformImage() { if (maskImage.ptr == IntPtr.Zero) { maskImage = cvlib.CvCreateImage(new CvSize(firstFrame.width, firstFrame.height), (int)cvlib.IPL_DEPTH_8U, 1); cvlib.CvSet(ref maskImage, new CvScalar(1, 1, 1, 1)); } // remove background //cvlib.CvSub(ref firstFrame, ref currentFrame, ref currentFrame, ref maskImage); // normalize CvHistogram hist = cvlib.CvCreateHist(1, new[] { 256 }, cvlib.CV_HIST_ARRAY, IntPtr.Zero, 1); cvlib.CvCalcHist(new[] { currentFrame.ptr }, ref hist, 0); cvlib.CvNormalizeHist(ref hist, 20000); cvlib.CvCalcBackProject(ref currentFrame, ref currentFrame, ref hist); cvlib.CvReleaseHist(ref hist); }
////// PART B/////// public void drawHistogram5a() { srcImage2 = Cv.LoadImage("5a.png", LoadMode.Color); float[] range = { 0, 255 }; float[][] ranges = { range }; int hist_size = 255; float min_value, max_value = 0; //Convert colour image into gray IplImage gray = Cv.CreateImage(srcImage2.Size, BitDepth.U8, 1); Cv.CvtColor(srcImage2, gray, ColorConversion.RgbToGray); //Create an image to hold the histogram IplImage histImage = Cv.CreateImage(srcImage2.Size, BitDepth.U8, 1); //Create a histogram to store the information from image CvHistogram hist = Cv.CreateHist(new int[] { hist_size }, HistogramFormat.Array, ranges, true); //Calculate the histogram and apply to hist Cv.CalcHist(gray, hist); //Grab the minimum & maximum values from the image Cv.GetMinMaxHistValue(hist, out min_value, out max_value); //Scale the bin values to fit to image representation Cv.Scale(hist.Bins, hist.Bins, ((double)histImage.Height) / max_value, 0); //Set background color to white histImage.Set(CvColor.White); int bin_w = Cv.Round((double)histImage.Width / hist_size); //Draw Values on Image - Here we will iterate across the histogram bins and apply the values to the image. for (int i = 0; i < hist_size; i++) { histImage.Rectangle(new CvPoint(i * bin_w, gray.Height), new CvPoint((i + 1) * bin_w, gray.Height - Cv.Round(hist.Bins[i])), CvColor.Black, 1, LineType.Link8, 0); } Cv.SaveImage("5ahistogram.png", histImage); }
// 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); }
CvMat CalculateBackProjection(CvMat _image, CvHistogram hist) { CvMat _backProject = new CvMat(_image.Rows, _image.Cols, MonoColorMatrix); using (CvMat _imageHSV = ConvertToHSV(_image)) // Convert the image to HSV 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 BGR, then it would split into B, G, R 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 // TODO: Why can't BackProjection accept CvMat? IplImage[] hsvPlanes = { Cv.GetImage(imgH), Cv.GetImage(imgS), Cv.GetImage(imgV) }; hist.CalcBackProject(hsvPlanes, _backProject); } return(_backProject); }
// 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); }
// 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 }
// 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 }
public void colorConversion(string fileName) { srcImage = Cv.LoadImage(fileName, LoadMode.Color); redImage = new IplImage(srcImage.Size, srcImage.Depth, srcImage.NChannels); greenImage = new IplImage(srcImage.Size, srcImage.Depth, srcImage.NChannels); blueImage = new IplImage(srcImage.Size, srcImage.Depth, srcImage.NChannels); for (var p = 0; p < srcImage.Height; p++) { for (var q = 0; q < srcImage.Width; q++) { CvColor pixels = srcImage[p, q]; redImage[p, q] = new CvColor { R = (byte)(255 - pixels.R) }; greenImage[p, q] = new CvColor { G = (byte)(255 - pixels.G) }; blueImage[p, q] = new CvColor { B = (byte)(255 - pixels.B) }; } } Cv.SaveImage("red.jpg", redImage); Cv.SaveImage("green.jpg", greenImage); Cv.SaveImage("blue.jpg", blueImage); float[] range = { 0, 255 }; float[][] ranges = { range }; int histogramSize = 255; float minimumValue, maximumValue = 0; grayscaleRed = Cv.CreateImage(redImage.Size, BitDepth.U8, 1); Cv.CvtColor(redImage, grayscaleRed, ColorConversion.RgbToGray); grayscaleGreen = Cv.CreateImage(greenImage.Size, BitDepth.U8, 1); Cv.CvtColor(greenImage, grayscaleGreen, ColorConversion.RgbToGray); grayscaleBlue = Cv.CreateImage(blueImage.Size, BitDepth.U8, 1); Cv.CvtColor(blueImage, grayscaleBlue, ColorConversion.RgbToGray); CvHistogram histogramR = Cv.CreateHist(new int[] { histogramSize }, HistogramFormat.Array, ranges, true); Cv.CalcHist(grayscaleRed, histogramR); Cv.GetMinMaxHistValue(histogramR, out minimumValue, out maximumValue); Cv.Scale(histogramR.Bins, histogramR.Bins, ((double)redImage.Height) / maximumValue, 0); redImage.Set(CvColor.White); CvHistogram histogramG = Cv.CreateHist(new int[] { histogramSize }, HistogramFormat.Array, ranges, true); Cv.CalcHist(grayscaleGreen, histogramG); Cv.GetMinMaxHistValue(histogramG, out minimumValue, out maximumValue); Cv.Scale(histogramG.Bins, histogramG.Bins, ((double)greenImage.Height) / maximumValue, 0); greenImage.Set(CvColor.White); CvHistogram histogramB = Cv.CreateHist(new int[] { histogramSize }, HistogramFormat.Array, ranges, true); Cv.CalcHist(grayscaleBlue, histogramB); Cv.GetMinMaxHistValue(histogramB, out minimumValue, out maximumValue); Cv.Scale(histogramB.Bins, histogramB.Bins, ((double)blueImage.Height) / maximumValue, 0); blueImage.Set(CvColor.White); int bin_red = Cv.Round((double)redImage.Width / histogramSize); int bin_green = Cv.Round((double)greenImage.Width / histogramSize); int bin_blue = Cv.Round((double)blueImage.Width / histogramSize); int r; for (r = 0; r < histogramSize; r++) { redImage.Rectangle(new CvPoint(r * bin_red, grayscaleRed.Height), new CvPoint((r + 1) * bin_red, grayscaleRed.Height - Cv.Round(histogramR.Bins[r])), CvColor.Black, -1, LineType.Link8, 0); } int g; for (g = 0; g < histogramSize; g++) { greenImage.Rectangle(new CvPoint(g * bin_green, grayscaleGreen.Height), new CvPoint((r + 1) * bin_green, grayscaleGreen.Height - Cv.Round(histogramG.Bins[g])), CvColor.Black, -1, LineType.Link8, 0); } int b; for (b = 0; b < histogramSize; b++) { blueImage.Rectangle(new CvPoint(b * bin_blue, grayscaleBlue.Height), new CvPoint((r + 1) * bin_blue, grayscaleBlue.Height - Cv.Round(histogramR.Bins[b])), CvColor.Black, -1, LineType.Link8, 0); } Cv.SaveImage("histogramRed.jpg", redImage); Cv.SaveImage("histogramGreen.jpg", greenImage); Cv.SaveImage("histogramBlue.jpg", blueImage); }
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); }
private double CalculateHistogramDistance(string jpg_path1, string jpg_path2) { int i, sch = 0; float[] range_0 = { 0, 256 }; float[][] ranges = { range_0 }; double tmp, dist = 0; IplImage src_img1, src_img2; IplImage[] dst_img1 = new IplImage[4]; IplImage[] dst_img2 = new IplImage[4]; CvHistogram[] hist1 = new CvHistogram[4]; CvHistogram hist2; src_img1 = IplImage.FromFile(jpg_path1, LoadMode.AnyDepth | LoadMode.AnyColor); // チャンネル数分の画像領域を確保 sch = src_img1.NChannels; for (i = 0; i < sch; i++) { dst_img1[i] = Cv.CreateImage(Cv.Size(src_img1.Width, src_img1.Height), src_img1.Depth, 1); } // ヒストグラム構造体を確保 int[] nHisSize = new int[1]; nHisSize[0] = 256; hist1[0] = Cv.CreateHist(nHisSize, HistogramFormat.Array, ranges, true); // 入力画像がマルチチャンネルの場合,画像をチャンネル毎に分割 if (sch == 1) { Cv.Copy(src_img1, dst_img1[0]); } else { Cv.Split(src_img1, dst_img1[0], dst_img1[1], dst_img1[2], dst_img1[3]); } for (i = 0; i < sch; i++) { Cv.CalcHist(dst_img1[i], hist1[i], false); Cv.NormalizeHist(hist1[i], 10000); if (i < 3) { Cv.CopyHist(hist1[i], ref hist1[i + 1]); } } Cv.ReleaseImage(src_img1); src_img2 = IplImage.FromFile(jpg_path2, LoadMode.AnyDepth | LoadMode.AnyColor); // 入力画像のチャンネル数分の画像領域を確保 for (i = 0; i < sch; i++) { dst_img2[i] = Cv.CreateImage(Cv.Size(src_img2.Width, src_img2.Height), src_img2.Depth, 1); } // ヒストグラム構造体を確保 nHisSize[0] = 256; hist2 = Cv.CreateHist(nHisSize, HistogramFormat.Array, ranges, true); // 入力画像がマルチチャンネルの場合,画像をチャンネル毎に分割 if (sch == 1) { Cv.Copy(src_img2, dst_img2[0]); } else { Cv.Split(src_img2, dst_img2[0], dst_img2[1], dst_img2[2], dst_img2[3]); } try { dist = 0.0; // ヒストグラムを計算,正規化して,距離を求める for (i = 0; i < sch; i++) { Cv.CalcHist(dst_img2[i], hist2, false); Cv.NormalizeHist(hist2, 10000); tmp = Cv.CompareHist(hist1[i], hist2, HistogramComparison.Bhattacharyya); dist += tmp * tmp; } dist = Math.Sqrt(dist); Cv.ReleaseHist(hist2); Cv.ReleaseImage(src_img2); } catch (OpenCVException ex) { Console.WriteLine("Error : " + ex.Message); } return(dist); }
// NOTE : Also seems not well written and craves optimization at places. P.A.N.A.R.G.O. // => frame = 8 bit greyscale CvMat static public void ContrastEnhancement(CvMat frame) { //CvMat originalFrame = frame; // return this if cannot enhance //if (frame.ElemType != MatrixType.U8C1) // frame = MatOps.Convert(frame, MatrixType.U8C1, 1 / 255.0 ); /////original histogram const int HistBinSize = 256; int[] histSizes = new int[1]; histSizes[0] = HistBinSize; CvHistogram hist = new CvHistogram(histSizes, HistogramFormat.Array); Cv.CalcArrHist(frame, hist, false); // size = 256 implied CvHistogram newHist = MatOps.CopyHistogram(hist); CvArr newHistBin = newHist.Bins; //double[] origVals = new double[hist.Bins.GetDims( 0 )]; List <double> origVals = new List <double>(HistBinSize); for (int i = 0; i < HistBinSize; i++) { double elem = newHistBin.GetReal1D(i); if (elem != 0) { origVals.Add(elem); } } // FIX : See no need for histL, since we have origVals //////histogram with only nonzero bins //CvMat histL = new CvMat( imageRows, imageCols, MatrixType.F32C1, new CvScalar( 0 ) ); //for (i = 0; i < origVals.size(); i++) // histL.at<float>( i, 0 ) = origVals.at( i ); List <double> peakValues = new List <double>(HistBinSize); //std::vector<int> peakValues; //////////3 bin search window for (int i = 1; i < origVals.Count - 2; ++i) { double elem = origVals[i]; if (elem > origVals[i - 1] && elem > origVals[i + 1]) { peakValues.Add(elem); } } if (peakValues.Count == 0) { //Console.Out.WriteLine( "Cannot enhance" ); return; // cannot enhance? } //////Upper threshold double threshUP = 0; for (int i = 0; i < peakValues.Count; ++i) { threshUP += peakValues[i]; } threshUP /= peakValues.Count; //////Lower threshold double threshDOWN = Math.Min((frame.Cols * frame.Rows), threshUP * origVals.Count) / 256.0; //Console.Out.WriteLine( "Enhance thresholds " + threshUP + "/" + threshDOWN ); //////histogram reconstruction CvArr histBins = hist.Bins; for (int i = 0; i < HistBinSize; ++i) { double histElem = histBins.GetReal1D(i); if (histElem > threshUP) { histBins.SetReal1D(i, threshUP); } else if (histElem <= threshUP && histElem >= threshDOWN) { continue; } else if (histElem < threshDOWN && histElem > 0) { histBins.SetReal1D(i, threshDOWN); } else if (histElem == 0) { continue; } } // accumulated values(?) double[] accVals = new double[HistBinSize]; //std::vector<int> accVals; accVals[0] = (histBins.GetReal1D(0)); for (int i = 1; i < HistBinSize; ++i) { accVals[i] = (accVals[i - 1] + histBins[i]); } byte[] lookUpTable = new byte[HistBinSize]; //cv::Mat lookUpTable = cv::Mat::zeros( hist.size(), CV_8UC1 ); for (int i = 0; i < HistBinSize; ++i) { lookUpTable[i] = (byte)(255.0 * accVals[i] / accVals[255]); } // assign computed values to input frame //Console.Out.Write( "Enhance-->" ); for (int i = 0; i < frame.Cols; ++i) { for (int j = 0; j < frame.Rows; ++j) { // there is NO mask, thus no need to check for; was: "if (mask.data)..." byte oldValue = (byte)frame.Get2D(j, i); byte newValue = lookUpTable[oldValue]; //if ((newValue <1 || newValue > 254) && (newValue != oldValue)) Console.Out.Write( oldValue + " " + newValue + "|"); frame.Set2D(j, i, newValue); //frame.SetReal2D( j, i, lookUpTable[ (int)(255.0 * frame.GetReal2D( j, i )) ] / 255.0); } } //Console.Out.WriteLine(); //frame = MatOps.Convert( frame, MatrixType.U8C1, 255.0 ); }
// Update and OnGUI are the main loops void Update() { if (DrawThresholdImageFlag) { DrawThresholdImage(videoSourceImage); } FindObjectScreenPosition(); if (_webcamTexture.isPlaying) { if (_webcamTexture.didUpdateThisFrame) { //convert Unity 2D texture from webcam to CvMat Texture2DToCvMat(); // Do some image processing with OpenCVSharp on this image frame ProcessImage(videoSourceImage); } } else { Debug.Log("Can't find camera!"); } if (Input.GetKeyDown(KeyCode.H)) // "h" key turns histogram screen on/off { histoWindowFlag = !histoWindowFlag; } if (trackFlag) { if (Input.GetKeyDown(KeyCode.B)) // "b" key turns back projection on/off { backprojWindowFlag = !backprojWindowFlag; } if (Input.GetKeyDown(KeyCode.T)) // "t" key turns tracking openCV window on { trackWindowFlag = !trackWindowFlag; } // Move an external game object based on the ROI being tracked if (gameObjectTracker) { ROIScreenToGameObject(rotatedBoxToTrack, gameObjectTracker); } } if (Input.GetMouseButtonDown(1)) { // Right mouse button Debug.Log("Tracking off"); trackFlag = false; _mouseIsDown = false; } else if (Input.GetMouseButtonDown(0)) { // Left mouse button if (!_mouseIsDown) { _mouseDownPos = Input.mousePosition; trackFlag = false; } _mouseIsDown = true; } if (Input.GetMouseButtonUp(0)) { // Left mouse button is up // If mouse went from down to up, then update the region of interest using the box if (_mouseIsDown) { // Calculate the histogram for the selected region of interest (ROI) _rectToTrack = CheckROIBounds(ConvertRect2CvRect(MakePixelBox(_mouseDownPos, _mouseLastPos))); if (DisplayROIFlag) { // Draw the region of interest to track DrawROIBox(videoSourceImage); } // Use Hue/Saturation histogram (not just the Hue dimension) _histogramToTrack = CalculateHSVHistogram(GetROI(videoSourceImage, _rectToTrack)); // Use Hue channel histogram only //_histogramToTrack = CalculateOneChannelHistogram (GetROI (videoSourceImage, _rectToTrack), 0, 179); lastPosition = new CvPoint(Mathf.FloorToInt(_rectToTrack.X), Mathf.FloorToInt(_rectToTrack.Y)); InitializeKalmanFilter(); trackFlag = true; } _mouseIsDown = false; } }