/// <summary> /// 反向投影(3維),需搭配3維的直方圖計算 /// </summary> /// <param name="template">樣板值方圖</param> /// <param name="observedSrcImg">要比對觀察的影像</param> /// <param name="isNormalized">是否要標準化</param> /// <param name="factor">標準化參數,預設1200000d</param> /// <returns>回除灰階的觀察影像(越白代表匹配的顏色越高)</returns> public static Image <Gray, Byte> HSVBackProject(DenseHistogram template, Image <Bgr, Byte> observedSrcImg, bool isNormalized = true, double factor = 1200000d) { try { DenseHistogram templateHist = new DenseHistogram(new int[] { template.BinDimension[0].Size, template.BinDimension[1].Size, template.BinDimension[2].Size }, new RangeF[] { new RangeF(0, h_max_range), new RangeF(0, s_max_range), new RangeF(0, v_max_range) }); template.Copy(templateHist); Image <Bgr, Byte> observedImg = observedSrcImg.Copy(); IntPtr hsv = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(observedImg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 3); IntPtr h_plane = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(observedImg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1); IntPtr s_plane = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(observedImg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1); IntPtr v_plane = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(observedImg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1); IntPtr[] observed_planes = new IntPtr[3] { h_plane, s_plane, v_plane }; //Image<Gray, Byte> h_planeImg = IplImagePointerToEmgucvImage<Gray, Byte>(h_plane); //Image<Gray, Byte> s_planeImg = IplImagePointerToEmgucvImage<Gray, Byte>(s_plane); CvInvoke.cvCvtColor(observedImg, hsv, Emgu.CV.CvEnum.COLOR_CONVERSION.CV_BGR2HSV); CvInvoke.cvSplit(hsv, h_plane, s_plane, v_plane, System.IntPtr.Zero); // 分离的单通道数组d if (isNormalized) { templateHist.Normalize(factor); } IntPtr backProj = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(observedImg), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 1); CvInvoke.cvZero(backProj); CvInvoke.cvCalcBackProject(observed_planes, backProj, templateHist); return(EmguFormatConvetor.IplImagePointerToEmgucvImage <Gray, Byte>(backProj)); } catch (Exception ex) { throw new InvalidOperationException(ex.Message); } }
/// <summary> /// 等化影像 /// </summary> /// <param name="srcImg">要等化的影像</param> /// <returns>回傳等化過的影像</returns> public static Image <Bgr, Byte> EqualizationImage(Image <Bgr, Byte> srcImg) { IntPtr dstImg = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(srcImg), IPL_DEPTH.IPL_DEPTH_8U, 3); IntPtr redImage = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(srcImg), IPL_DEPTH.IPL_DEPTH_8U, 1); IntPtr greenImage = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(srcImg), IPL_DEPTH.IPL_DEPTH_8U, 1); IntPtr blueImage = CvInvoke.cvCreateImage(CvInvoke.cvGetSize(srcImg), IPL_DEPTH.IPL_DEPTH_8U, 1); CvInvoke.cvSplit(srcImg, blueImage, greenImage, redImage, IntPtr.Zero); CvInvoke.cvEqualizeHist(blueImage, blueImage); CvInvoke.cvEqualizeHist(greenImage, greenImage); CvInvoke.cvEqualizeHist(redImage, redImage); CvInvoke.cvMerge(blueImage, greenImage, redImage, IntPtr.Zero, dstImg); return(EmguFormatConvetor.IplImagePointerToEmgucvImage <Bgr, Byte>(dstImg)); }
/// <summary> /// 2D值方圖(色調與飽和度) 的繪製,使用emgucv提供的cvInvoke去調用opencv的函式 /// 繪製與範例的值方圖一致目前先採用 /// </summary> /// <param name="histDense"></param> /// <returns>回傳繪製值方圖的影像,直接顯示即可</returns> public static Image <Bgr, Byte> Generate2DHistogramImgForDraw(DenseHistogram histDense) { try { float max_value = 0.0f; int[] a1 = new int[100]; int[] b1 = new int[100]; float ax = 0; int h_bins = histDense.BinDimension[0].Size; int s_bins = histDense.BinDimension[1].Size; //1.使用Intptr // CvInvoke.cvGetMinMaxHistValue(histPtr, ref ax, ref max_value, a1, b1); //2.emgucv的DenseHistogram資料格式也可使用cvInvoke的openCV函式 CvInvoke.cvGetMinMaxHistValue(histDense, ref ax, ref max_value, a1, b1); /* 设置直方图显示图像 */ int height = 300; int width; //如果設定的bins超過視窗設定的顯示範圍,另外給予可以符合用額外的彈出視窗顯示的值 if (h_bins * s_bins > 800) { width = h_bins * s_bins * 2; } else { width = 800; } IntPtr hist_img = CvInvoke.cvCreateImage(new System.Drawing.Size(width, height), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 3); CvInvoke.cvZero(hist_img); /* 用来进行HSV到RGB颜色转换的临时单位图像 */ IntPtr hsv_color = CvInvoke.cvCreateImage(new System.Drawing.Size(1, 1), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 3); IntPtr rgb_color = CvInvoke.cvCreateImage(new System.Drawing.Size(1, 1), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 3); int bin_w = width / (h_bins * s_bins); for (int h = 0; h < h_bins; h++) { for (int s = 0; s < s_bins; s++) { int i = h * s_bins + s; /* 获得直方图中的统计次数,计算显示在图像中的高度 */ // //取得值方圖的數值位置,以便之後存成檔案 //1.Intptr //double bin_val = CvInvoke.cvQueryHistValue_2D(histPtr, h, s); //2.DenseHistogram double bin_val = CvInvoke.cvQueryHistValue_2D(histDense, h, s); int intensity = (int)System.Math.Round(bin_val * height / max_value); /* 获得当前直方图代表的颜色,转换成RGB用于绘制 */ CvInvoke.cvSet2D(hsv_color, 0, 0, new Emgu.CV.Structure.MCvScalar(h * 180.0f / h_bins, s * 255.0f / s_bins, 255, 0)); CvInvoke.cvCvtColor(hsv_color, rgb_color, COLOR_CONVERSION.CV_HSV2BGR); Emgu.CV.Structure.MCvScalar color = CvInvoke.cvGet2D(rgb_color, 0, 0); CvInvoke.cvRectangle(hist_img, new System.Drawing.Point(i * bin_w, height), new System.Drawing.Point((i + 1) * bin_w, height - intensity), color, -1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0); } } /* *使用openCV函式繪製 * CvInvoke.cvNamedWindow("Source"); * CvInvoke.cvShowImage("Source", this.srcImage); * CvInvoke.cvNamedWindow("H-S Histogram"); * CvInvoke.cvShowImage("H-S Histogram", hist_img); * CvInvoke.cvWaitKey(0); * */ return(EmguFormatConvetor.IplImagePointerToEmgucvImage <Bgr, Byte>(hist_img)); } catch (Exception ex) { throw new InvalidOperationException(ex.Message); } }
////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// drawing hue color still have problem /// 1D值方圖(色調) 的繪製,使用emgucv提供的cvInvoke去調用opencv的函式 /// 繪製與範例的值方圖一致目前先採用 /// </summary> /// <param name="histDense"></param> /// <returns>回傳繪製值方圖的影像,直接顯示即可</returns> public static Image <Bgr, Byte> Generate1DHistogramImgForDraw(DenseHistogram histDense) { try { float max_value = 0.0f; int[] a1 = new int[100]; int[] b1 = new int[100]; float ax = 0; int h_bins = histDense.BinDimension[0].Size; //1.使用Intptr // CvInvoke.cvGetMinMaxHistValue(histPtr, ref ax, ref max_value, a1, b1); //2.emgucv的DenseHistogram資料格式也可使用cvInvoke的openCV函式 CvInvoke.cvGetMinMaxHistValue(histDense, ref ax, ref max_value, a1, b1); /* 取最大的顏色的位置 並換成RGB * foreach (int index in a1) * { * Console.WriteLine("location="+index+",H Color = "+ HueToBgr(index * 180.0d / h_bins)); * } * */ /* 设置直方图显示图像 */ int height = 240; int width = 800; IntPtr hist_img = CvInvoke.cvCreateImage(new System.Drawing.Size(width, height), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 3); CvInvoke.cvZero(hist_img); /* 用来进行HSV到RGB颜色转换的临时单位图像 */ IntPtr hsv_color = CvInvoke.cvCreateImage(new System.Drawing.Size(1, 1), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 3); IntPtr rgb_color = CvInvoke.cvCreateImage(new System.Drawing.Size(1, 1), Emgu.CV.CvEnum.IPL_DEPTH.IPL_DEPTH_8U, 3); int bin_w = width / (h_bins); for (int h = 0; h < h_bins; h++) { /* 获得直方图中的统计次数,计算显示在图像中的高度 */ // //取得值方圖的數值位置,以便之後存成檔案 //2.DenseHistogram double bin_val = CvInvoke.cvQueryHistValue_1D(histDense, h); int intensity = (int)System.Math.Round(bin_val * height / max_value); /* 获得当前直方图代表的hue颜色,转换成RGB用于绘制 */ CvInvoke.cvRectangle(hist_img, new System.Drawing.Point(h * bin_w, height), new System.Drawing.Point((h + 1) * bin_w, height - intensity), HueToBgr(h * 180.0d / h_bins), -1, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, 0); } /* *使用openCV函式繪製 * CvInvoke.cvNamedWindow("Source"); * CvInvoke.cvShowImage("Source", this.srcImage); * CvInvoke.cvNamedWindow("H-S Histogram"); * CvInvoke.cvShowImage("H-S Histogram", hist_img); * CvInvoke.cvWaitKey(0); * */ return(EmguFormatConvetor.IplImagePointerToEmgucvImage <Bgr, Byte>(hist_img)); } catch (Exception ex) { throw new InvalidOperationException(ex.Message); } }