夜场酒吧娱乐ktv类企业网站源码,成功案例 品牌网站,银行网站模板免费下载,地方门户网站带手机版2014-02-0610325 0C# 檢舉文章 過年結束了#xff0c;雖然還是學生所以其實還有兩個禮拜的假期#xff0c;不過為了不讓自己發慌#xff0c;趁著假期多利用充實自己#xff0c;所以提早回到開工狀態#xff0c;而這次總算要把一直說的自己動手繪製猜色直方圖文章寫出。 …2014-02-0610325 0C# 檢舉文章 過年結束了雖然還是學生所以其實還有兩個禮拜的假期不過為了不讓自己發慌趁著假期多利用充實自己所以提早回到開工狀態而這次總算要把一直說的自己動手繪製猜色直方圖文章寫出。 在很之前[EmguCV|WinForm] 使用EmguCV內建直方圖工具繪製直方圖(Histogram)直方圖(Histogram)系列 (1) 篇中可以透過EmguCV內建的HistogramBox與HistogramViewer來幫助我們呈現一張圖像的直方圖資訊 不過有時後我們仍希望可以直接用顏色來呈現一張圖像的色彩分布而這篇便是要來實作這部分。 前言 過年結束了雖然還是學生所以其實還有兩個禮拜的假期不過為了不讓自己發慌趁著假期多利用充實自己所以提早回到開工狀態而這次總算要把一直說的自己動手繪製猜色直方圖文章寫出。 在很之前[EmguCV|WinForm] 使用EmguCV內建直方圖工具繪製直方圖(Histogram)直方圖(Histogram)系列 (1)篇中可以透過EmguCV內建的HistogramBox與HistogramViewer來幫助我們呈現一張圖像的直方圖資訊 不過有時後我們仍希望可以直接用顏色來呈現一張圖像的色彩分布而這篇便是要來實作這部分。 PS:建議先看過[EmguCV|C#]使用EmguCV的DenseHistogram類別計算與紀錄圖像直方圖直方圖(Histogram)系列(2) 繪製值方圖 1.繪製的呈現結果 這篇文章會教導如何手動繪製完如下值方圖圖像 上述的圖為hue色相的色彩分佈圖因為我把Bin值設定為16所以量化後的顏色區間的變化比較簡單至於Bin是什麼可以參考先前的文章 [EmguCV|C#]使用EmguCV的DenseHistogram類別計算與紀錄圖像直方圖直方圖(Histogram)系列(2) 不過由於2維能呈現的資訊比較少所以在繪製這樣的直方圖圖像時我是採用HSV色彩空間因為HSV色彩空間可以把色相分離出來純看色彩的基本顏色(可見光)而原先的RGB色彩空間由於顏色是混在一起所以難以呈現(如下RGB色彩空間示意圖) 另外本篇的繪製會搭配[EmguCV|C#]使用EmguCV的CvInvoke計算值方圖(Histogram)直方圖(Histogram)系列(3)文章使用CvInvoke來計算圖像的值方圖資訊到DenseHistogarm那麼接下來我們來看一下如何繪製吧 2.繪製的方式 我們在做值方圖的繪製時其實是把計算好的DenseHistogarm資料拿取出來一一取得各個Bin所計算好的資訊並把它繪製到一張ImageBgr,byte型態的圖像上所以最後呈現時其實是在呈現一張圖片。 這邊我們先來看繪製Hue色相的直方圖 1.初始化參數 這邊我們需要在乎的是max_value 此變數是用來存放直方圖中所找到的最高累積區塊的數值例如上述的粉筆圖像的值方圖中左邊紅色的區塊所累積的顏色是最多假設他是300表示在這張圖中有300個落在這個紅色區塊中的顏色。 而這個數值可以用來做為之後繪製到圖上時用來計算出個顏色區塊顯示在圖像上的座標位置h_bins 則是取得我們之前計算時所設定的顏色區間設定區塊。 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; 2.取得直方圖的最大與最小累積值的區塊(Bin) CvInvoke.cvGetMinMaxHistValue(histDense, ref ax, ref max_value, a1, b1); 3.設定一個要把直方圖資料繪製到的圖像的寬高並初始化 //設定值方圖圖像顯示的寬高
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); 4.計算出顯示在圖像上的bin寬度 這是為了讓我們原先所設定的Bin數量可以合理的顯示在一張我們所想要設定的寬度圖像上例如我們這邊打算顯示到800*240圖像上因為寬是800為了可以讓我所設定的50個bins合理的完整顯示所以要做個計算 int bin_w width / (h_bins); //h_bin設定為50 5.依序取得值方圖中的每個Bin區塊資料並計算危險是到圖像上的位置與顏色 依序尋訪每一個Bin區塊並擷取bin的數值顏色區塊的累積值並計算如果顯示到240高的圖像上要顯示的位置以及要顯示的顏色 for (int h 0; h h_bins; h)
{/** 取得直方圖的統計資料計算值方圖中的所有顏色中最高統計的數值作為實際顯示時的圖像高 *///取得值方圖的數值位置,以便之後存成檔案double bin_val CvInvoke.cvQueryHistValue_1D(histDense, h);//計算取得的bin值要顯示在240高的圖像上時的位置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);} 其中HueToBgr的方法如下 用來將色相的數值轉換成RGB顏色 /// summary/// hue色相轉換成rgb color/// /summary/// param namehue/param/// returns/returnsprivate static MCvScalar HueToBgr(double hue){int[] rgb new int[3];int p, sector;int[,] sector_data { { 0, 2, 1 }, { 1, 2, 0 }, { 1, 0, 2 }, { 2, 0, 1 }, { 2, 1, 0 }, { 0, 1, 2 } };hue * 0.033333333333333333333333333333333f;sector (int)Math.Floor(hue);p (int)Math.Round(255 * (hue - sector));//p ^ sector 1 ? 255 : 0;if ((sector 1) 1) p ^ 255;else p ^ 0;rgb[sector_data[sector, 0]] 255;rgb[sector_data[sector, 1]] 0;rgb[sector_data[sector, 2]] p;MCvScalar scalar new MCvScalar(rgb[2], rgb[1], rgb[0], 0);return scalar;} 6.把得到的值方圖圖像轉換為EmguCV使用的imageBgr,Byte型態 原先我們在計算時所用的存放型態是Intptr可以參考[EmguCV|OpenCV|C#] 轉換支援存取OpenCV Iplmage的IntPtr型態為EmguCV儲存圖像的型態所寫的內容 以下是其中一種方式 ImageBgr, Byte hist_emgu_img new ImageBgr, Byte(new System.Drawing.Size(width, height));
CvInvoke.cvCopy(hist_img, hist_emgu_img.Ptr, IntPtr.Zero);
return hist_emgu_img; 3.繪製HS直方圖的方法 這邊我們來快速帶一下如何繪製HS直方圖至於為什麼會需要用到S(飽和度)呢 有可能我們會希望透過飽和度增加可以分析有亮度時影像的辨識穩定度不過如果分太細因為細緻度增加過頭了反而只會讓辨識下降。 1.初始化參數 這邊多了s_bin因為我們也會需要看到飽和度的變化 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; 2.取得直方圖的最大與最小累積值的區塊(Bin) CvInvoke.cvGetMinMaxHistValue(histDense, ref ax, ref max_value, a1, b1); 3.設定一個要把直方圖資料繪製到的圖像的寬高並初始化 因為除了顯示色相的Bin之外我們還需要顯示飽和度所以可能原先的寬會超過如果超過在而外計算一個剛好的寬做為顯示的影像大小 //設定值方圖圖像顯示的寬高
int height 300;
int width;
//如果設定的bins超過視窗設定的顯示範圍,另外給予可以符合用額外的彈出視窗顯示的值,因為要同時看到h與s的bin值顯示的圖像寬可能會太寬
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); 4.初始化用來存放把色相值方圖的資料轉換成要顯示出來的RGB數值空間 因為我們原先的直方圖是Hsv空間但是當我們要繪製到圖像來看時因為所記錄的RGB空間(ImageBgr,byte型態)為了能夠做正確的顯示所以我們之後需要做一個色彩空間轉換 //用來存放從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); 5.計算出顯示在圖像上的bin寬度 int bin_w width / (h_bins * s_bins); 6.依序取得值方圖中的每個Bin區塊資料並計算危險是到圖像上的位置與顏色 for (int h 0; h h_bins; h)
{for (int s 0; s s_bins; s){int i h * s_bins s;/** 取得直方圖的統計資料計算值方圖中的所有顏色中最高統計的數值作為實際顯示時的圖像高 *///取得值方圖的數值位置,以便之後存成檔案double bin_val CvInvoke.cvQueryHistValue_2D(histDense, h, s);int intensity (int)System.Math.Round(bin_val * height / max_value);/** 取得現在抓取的直方圖的hue顏色並為了顯示成圖像可觀看轉換成RGB色彩 */CvInvoke.cvSet2D(hsv_color, 0, 0, new Emgu.CV.Structure.MCvScalar(h * 180.0f / h_bins, s * 255.0f / s_bins, 255, 0)); //這邊用來計算色相與飽和度的統計資料轉換到圖像上 hsv_color的數值CvInvoke.cvCvtColor(hsv_color, rgb_color, COLOR_CONVERSION.CV_HSV2BGR); //在把hsv顏色空間轉換為RGBEmgu.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);}
} 7.把得到的值方圖圖像轉換為EmguCV使用的imageBgr,Byte型態 原先我們在計算時所用的存放型態是Intptr可以參考[EmguCV|OpenCV|C#] 轉換支援存取OpenCV Iplmage的IntPtr型態為EmguCV儲存圖像的型態所寫的內容 以下是其中一種方式 ImageBgr, Byte hist_emgu_img new ImageBgr, Byte(new System.Drawing.Size(width, height));
CvInvoke.cvCopy(hist_img, hist_emgu_img.Ptr, IntPtr.Zero);
return hist_emgu_img;顯示結果