[EmguCV|C#]使用CvInvoke自己繪製色彩直方圖-直方圖(Hitsogram)系列(4)


  • 10325
  • ?0
  • C#
  • ?檢舉文章

過年結束了,雖然還是學生所以其實還有兩個禮拜的假期,不過為了不讓自己發慌,趁著假期多利用充實自己,所以提早回到開工狀態,而這次總算要把一直說的自己動手繪製猜色直方圖文章寫出。?

在很之前[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.繪製的呈現結果

這篇文章會教導如何手動繪製完如下值方圖圖像:

hsv_h_histogram

上述的圖為hue色相的色彩分佈圖,因為我把Bin值設定為16,所以量化後的顏色區間的變化比較簡單-至於Bin是什麼可以參考先前的文章?[EmguCV|C#]使用EmguCV的DenseHistogram類別計算與紀錄圖像直方圖-直方圖(Histogram)系列(2)

?

不過由於2維能呈現的資訊比較少,所以在繪製這樣的直方圖圖像時,我是採用HSV色彩空間,因為HSV色彩空間可以把色相分離出來,純看色彩的基本顏色(可見光),而原先的RGB色彩空間由於顏色是混在一起,所以難以呈現(如下RGB色彩空間示意圖)

RGB_color_solid_cube

?

另外本篇的繪製會搭配[EmguCV|C#]使用EmguCV的CvInvoke計算值方圖(Histogram)-直方圖(Histogram)系列(3)文章,使用CvInvoke來計算圖像的值方圖資訊到DenseHistogarm,那麼接下來我們來看一下如何繪製吧

?

2.繪製的方式

我們在做值方圖的繪製時,其實是把計算好的DenseHistogarm資料拿取出來,一一取得各個Bin所計算好的資訊,並把它繪製到一張Image<Bgr,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 name="hue"></param>/// <returns></returns>private 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使用的image<Bgr,Byte>型態

原先我們在計算時所用的存放型態是Intptr,可以參考[EmguCV|OpenCV|C#] 轉換支援存取OpenCV Iplmage的IntPtr型態為EmguCV儲存圖像的型態所寫的內容

以下是其中一種方式:

Image<Bgr, Byte> hist_emgu_img = new Image<Bgr, 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空間(Image<Bgr,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使用的image<Bgr,Byte>型態

原先我們在計算時所用的存放型態是Intptr,可以參考[EmguCV|OpenCV|C#] 轉換支援存取OpenCV Iplmage的IntPtr型態為EmguCV儲存圖像的型態所寫的內容

以下是其中一種方式:

Image<Bgr, Byte> hist_emgu_img = new Image<Bgr, Byte>(new System.Drawing.Size(width, height));
CvInvoke.cvCopy(hist_img, hist_emgu_img.Ptr, IntPtr.Zero);
return hist_emgu_img;

?

顯示結果

hsv_hs_histogram

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/387655.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/387655.shtml
英文地址,請注明出處:http://en.pswp.cn/news/387655.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

G.點我

鏈接&#xff1a;https://ac.nowcoder.com/acm/contest/903/G 題意&#xff1a; X腿與隊友到河北省來參加2019河北省大學生程序設計競賽&#xff0c;然而這場比賽的題目難度實在是太高了。比賽開始一個小時后&#xff0c;X腿仍然沒有做出一個題。這時候&#xff0c;X腿驚訝的發…

輪廓的查找、表達、繪制、特性及匹配(How to Use Contour? Find, Component, Construct, Features Match)

前言 輪廓是構成任何一個形狀的邊界或外形線。前面講了如何根據色彩及色彩的分布&#xff08;直方圖對比和模板匹配&#xff09;來進行匹配&#xff0c;現在我們來看看如何利用物體的輪廓。包括以下內容&#xff1a;輪廓的查找、表達方式、組織方式、繪制、特性、匹配。 查…

Android:IntentService的學習

在Android的四大組件中&#xff0c;Service排行老二&#xff0c;在Android中的主要作用是后臺服務&#xff0c;進行與界面無關的操作。由于Service運行在主線程&#xff0c;所以進行異步操作需要在子線進行。為此Android為我們提供了IntentService。 IntentService是一個抽象類…

智能商業大會構造信息化交流平臺

在快速發展的當今社會&#xff0c;所有事物都在日新月異地變化著&#xff0c;相較于過去的傳統商業的變化速度&#xff0c;現今基于數據的互聯網商業變化速度高出了一個量級&#xff0c;同時市場對于企業的應對速度也有了更高的要求&#xff0c;然而面對大體量的數據&#xff0…

itcast-ssh-crm實踐

分析 BaseDao 文件上傳 轉載于:https://www.cnblogs.com/hellowq/p/10209761.html

分類器大牛們

David Lowe&#xff1a;Sift算法的發明者&#xff0c;天才。 Rob Hess&#xff1a;sift的源碼OpenSift的作者&#xff0c;個人主頁上有openSift的下載鏈接&#xff0c;Opencv中sift的實現&#xff0c;也是參考這個。 Koen van de Sande&#xff1a;作者給出了sift,densesift,co…

go 成長路上的坑(1)

一、先來看一段代碼 package mainimport "fmt"type X struct{}func (x *X) test(){println("h1",x) } func main(){a : X{} a.test()(&X{}).test()(X{}).test() } 猜猜他的結果 二、揭曉答案 package mainimport "fmt"type X struct{}func (…

利用python腳本程序監控文件被修改

需求&#xff1a;利用python編寫監控程序&#xff0c;監控一個文件目錄&#xff0c;當目錄下的文件發生改變時&#xff0c;實現有修改就發報警郵件 郵件使用QQ郵箱&#xff0c;需要開啟smtp&#xff0c;使用手機發生短信&#xff0c;騰訊會給你發郵箱密碼。如下所示&#xff1a…

Oracle RAC

環境如下&#xff1a; Linux操作系統&#xff1a;Centos 6.5 64bit &#xff08;這個版本的redhat 6內核等OS在安裝grid最后執行root.sh時會出現crs-4124&#xff0c;是oracle11.2.0.1的bug&#xff09; VMware version&#xff1a;Workstation 8.0.3 build-703057 Oracle…

好程序員web前端分享MVVM框架Vue實現原理

好程序員web前端分享MVVM框架Vue實現原理&#xff0c;Vue.js是當下很火的一個JavaScript MVVM庫&#xff0c;它是以數據驅動和組件化的思想構建的。相比于Angular.js和react.js更加簡潔、更易于理解的API&#xff0c;使得我們能夠快速地上手并使用Vue.js。?1.什么是MVVM呢&…

HDU - 3516 Tree Construction

HDU - 3516 思路&#xff1a; 平行四邊形不等式優化dp &#xff1a;&#xff09; 代碼&#xff1a; #pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc.h> using namespace std; #define y1 y11 #define fi first #define se…

各類總線傳輸速率

1. USB總線 USB1.1&#xff1a; -------低速模式(low speed)&#xff1a;1.5Mbps -------全速模式(full speed)&#xff1a; 12Mbps USB2.0&#xff1a;向下兼容。增加了高速模式&#xff0c;最大速率480Mbps。 -------高速模式(high speed)&#xff1a; 25~480Mbps US…

Activiti多人會簽例子

Activiti中提供了多實例任務&#xff08;for-each&#xff09;將多實例應到到UserTask中可以實現會簽功能。 Multi-instance (for each) Description A multi-instance activity is a way of defining repetition for a certain step in a business process. In programming …

Django 【認證系統】auth

本篇內容 介紹Django框架提供的auth 認證系統 方法&#xff1a; 方法名 備注 create_user 創建用戶 authenticate 登錄驗證 login 記錄登錄狀態 logout 退出用戶登錄 is_authenticated 判斷用戶是否登錄 login_required裝飾器 進行登錄判斷 引入模塊 from django.…

兒科常見疾病的中成藥療法

孩子感冒&#xff0c;分清寒熱是關鍵——兒童風寒感冒和風熱感冒的中成藥內服外治法 兒童不養兒不知父母恩&#xff0c;每個人恐怕都只有自己做了父母&#xff0c;才能感受到父母的愛。嬰幼兒正處于最初的發育期&#xff0c;抵抗力弱&#xff0c;有個感冒發燒的也是常有的事兒。…

物化視圖

有個項目因為有比較多的查詢匯總&#xff0c;考慮到速度&#xff0c;所以使用了物化視圖。簡單的把用到的給整理了下。先看簡單創建語句&#xff1a;create materialized view mv_materialized_test refresh force on demand start with sysdate nextto_date(concat(to_char( s…

為什么直接ping知乎的ip不能訪問知乎的網站,而百度就可以?

結論&#xff1a; 簡單的說&#xff0c;就是baidu有錢。 正文&#xff1a; 大型網站依靠自身稀稀落落的服務器很難滿足網頁“秒開”的用戶需求&#xff0c;會加入CDN加速的隊伍。 當用戶訪問 http://www.zhihu.com 時&#xff0c;域名解析到距離用戶最近的CDN服務器的公網IP&am…

皮膚病

小偏方治百病/《國醫絕學健康館》編委會編.—重慶&#xff1a;重慶出版社&#xff0c;2010.3&#xff08;國醫絕學健康館&#xff09; 濕疹 苦參湯熏洗治陰囊濕疹方 苦參、蛇麻子中藥各50克&#xff0c;混合后&#xff0c;在晚上煎湯&#xff0c;可直接放在臉盆中煎。煎好后&am…

MySQL-ProxySQL中間件(一)| ProxySQL基本概念

目錄 MySQL-ProxySQL中間件&#xff08;一&#xff09;| ProxySQL基本概念&#xff1a; https://www.cnblogs.com/SQLServer2012/p/10972593.htmlMySQL-ProxySQL中間件&#xff08;二&#xff09;| Admin Schemas介紹&#xff1a;https://www.cnblogs.com/SQLServer2012/p/109…

01 ftp上傳簡單示例服務端

import json import socket import structserver socket.socket() server.bind((127.0.0.1,8001)) server.listen() conn,addr server.accept()#首先接收文件的描述信息的長度 struct_data_len conn.recv(4) data_len struct.unpack(i,struct_data_len)[0]# 通過文件信息的…