织梦CMS - 轻松建站从此开始!

罗索

OpenCV统计应用-CvHistogram直方图资料

落鹤生 发布于 2010-04-20 10:26 点击:次 
CvHistogram算是一個比較複雜的資料結構,由於它在維度小於二的可以用密集的資料結構,CvMatND來設計,可以當它的直方圖維度大於二的時候,就必須要用到稀疏矩陣,CvSparseMat的方式
TAG:

CvHistogram可以提供直方圖的計算,並且可以支援多個維度的直方圖設計,但是在繪製直方圖圖形的時候就需要自己用繪圖函式來繪製,CvHistogram算是一個比較複雜的資料結構,由於它在維度小於二的可以用密集的資料結構,CvMatND來設計,可以當它的直方圖維度大於二的時候,就必須要用到稀疏矩陣,CvSparseMat的方式,下面就是用CvHistogram結構計算一維直方圖的例子

CvHistogram一維設計

  1. #include <cv.h> 
  2. #include <highgui.h> 
  3. #include <stdio.h> 
  4.  
  5. int HistogramBlock = 256; 
  6. float HistogramRange1[2]={0,255}; 
  7. float *HistogramRange[1]={&HistogramRange1[0]}; 
  8.  
  9. int main() 
  10.      IplImage *Image1; 
  11.      CvHistogram *Histogram1; 
  12.      IplImage *HistogramImage1; 
  13.  
  14.      Image1=cvLoadImage("Riverbank.jpg",0); 
  15.  
  16.      Histogram1 = cvCreateHist(1,&HistogramBlock,CV_HIST_ARRAY,HistogramRange); 
  17.      HistogramImage1 = cvCreateImage(cvSize(256,300),8,3); 
  18.      HistogramImage1->origin=1; 
  19.  
  20.      cvCalcHist(&Image1,Histogram1); 
  21.  
  22.      printf("type is : %d\n",Histogram1->type); 
  23.      printf("Low Bound is : %.f\n",Histogram1->thresh[0][0]); 
  24.      printf("Up Bound is : %.f\n",Histogram1->thresh[0][1]); 
  25.      printf("The Block is : %d\n",((CvMatND *) Histogram1->bins)->dim[0].size); 
  26.  
  27.      printf("\nGray Level Values:\n"); 
  28.     for(int i=0;i<HistogramBlock;i++) 
  29.      { 
  30.          printf("%.f \n",((CvMatND *) Histogram1->bins)->data.fl[i]); 
  31.          cvLine(HistogramImage1,cvPoint(i,0),cvPoint(i,(int)(cvQueryHistValue_1D(Histogram1,i)/10)),CV_RGB(127,127,127)); 
  32.      } 
  33.  
  34.      cvNamedWindow("Histogram",1); 
  35.      cvNamedWindow("Riverbank",1); 
  36.      cvShowImage("Riverbank",Image1); 
  37.      cvShowImage("Histogram",HistogramImage1); 
  38.      cvWaitKey(0); 

原始圖片:

執行結果:

跟前面直接用矩陣累加設計出的統計直方圖一樣,到最後還是要自己用繪圖函式自己畫,CvHistogram這個資料結構的特色,它可以設定要用幾個區塊來呈現,這邊設立為256個區塊,而實際上,它可以用比較模糊的方式設定直方圖的區域,也就是可以小於256個的區塊數,是利用切割成n等分的方式,然後它可以自行設定上界(Up Bound)以及下界(Low Bound),在灰階圖裡面數據的範圍為0~255,而CvHistogram資料結構可以設立為上界30,下界200這樣的方式縮小範圍,而0~29,201~266這範圍內的數據將不會被計算,下面是CvHistogram資料結構的內容,分別為CV_HIST_ARRAY及CV_HIST_SPARSE兩種

1.

2.

CvHistogram的type固定都為CV_HIST_MAGIC_VAL這的參數,與上面程式cvCreateHist()所設定的CV_HIST_ARRAY無關,這也許是OpenCV裡面對於CvHistogram這個結構設計不良的地方,而對於CvHistogram資料結構的參數,定義如下

#define CV_HIST_ARRAY 0
#define CV_HIST_SPARSE 1
#define CV_HIST_TREE CV_HIST_SPARSE

因此,它的參數只有CV_HIST_ARRAY的多維矩陣CvMatND以及CV_HIST_SPARSE的稀疏矩陣CvSparseMat資料結構,而它的thresh是放上下界的資料,thresh2是放動態的維度上下界資料,而一般的直方圖數據資料都是放在bins裡面.而CvHistogram內的CvMatND結構則是在做快速初始化,bins以及mat都是使用同一個記憶體空間,而將直方圖資料的提取就要用到cvQueryHistValue_1D()這個函式了.

接著是將直方圖的空間分區塊的方式實作,將它分為50塊,並且上界為30,下界為200

CvHistogram結構區塊與上下界

  1. #include <cv.h> 
  2. #include <highgui.h> 
  3. #include <stdio.h> 
  4.  
  5. int HistogramBlock = 50; 
  6. int HistogramBlockWidth; 
  7. float HistogramRange1[2]={30,200}; 
  8. float *HistogramRange[1]={&HistogramRange1[0]}; 
  9.  
  10. int main() 
  11.      IplImage *Image1; 
  12.      CvHistogram *Histogram1; 
  13.      IplImage *HistogramImage1; 
  14.      CvPoint Point1; 
  15.      CvPoint Point2; 
  16.  
  17.      Image1=cvLoadImage("Riverbank.jpg",0); 
  18.  
  19.      Histogram1 = cvCreateHist(1,&HistogramBlock,CV_HIST_ARRAY,HistogramRange); 
  20.      HistogramImage1 = cvCreateImage(cvSize(256,300),8,3); 
  21.      cvSetZero(HistogramImage1); 
  22.      HistogramImage1->origin=1; 
  23.      HistogramBlockWidth=256/HistogramBlock; 
  24.      printf("The Bolck Width is : %d\n",HistogramBlockWidth); 
  25.      cvCalcHist(&Image1,Histogram1); 
  26.  
  27.      printf("Gray Level Values:\n"); 
  28.     for(int i=0;i<histogramblock;i++) 
  29.      { 
  30.          printf("%.f \n",((CvMatND *) Histogram1->bins)->data.fl[i]); 
  31.          Point1=cvPoint(i*HistogramBlockWidth,0); 
  32.          Point2=cvPoint((i+1)*HistogramBlockWidth,(int)cvQueryHistValue_1D(Histogram1,i)/50); 
  33.  
  34.          cvRectangle(HistogramImage1,Point1,Point2,CV_RGB(127,127,127)); 
  35.      } 
  36.  
  37.      cvNamedWindow("Histogram",1); 
  38.      cvNamedWindow("Riverbank",1); 
  39.      cvShowImage("Riverbank",Image1); 
  40.      cvShowImage("Histogram",HistogramImage1); 
  41.      cvWaitKey(0); 

執行結果:

因此,這邊就用cvRectangle()的方式來表達,對於CvHistogram這個資料結構,為什麼可以任意定義上下界以及區塊的個數呢?因為CvHistogram使用的是Look-up table(LUT)的方式,也就是查表法,開一個256大小空間的陣列,利用比例的縮放,縮放的數據存入Look-up table裡面,在利用索引的方式對應,而使用Look-up table最大的缺點為,無法取得很精確的數據,由於它是被比例縮放過的,因此除了範圍為256的可以求的完整的數值,LUT的用法會在後面使用到.

對於其他維度的直方圖,它的做法如下

三維直方圖擷取

  1. /**************************** 
  2. * change image histogram example 
  3. * date:08-11-1 
  4. * author: wml 
  5. * copyright:1.0 
  6. *****************************/ 
  7. #include <cv.h> 
  8. #include <highgui.h> 
  9. #include <cvaux.h> 
  10. #include <cxcore.h> 
  11. #include <iostream.h> 
  12. #include <string.h> 
  13. #include <stdio.h> 
  14.  
  15. #pragma comment(lib,"cv") 
  16. #pragma comment(lib,"cvaux") 
  17. #pragma comment(lib,"cxcore") 
  18. #pragma comment(lib,"highgui") 
  19.  
  20. int Histogram3DBlock[3] = {256,256,256}; 
  21. float HistogramRange1[6]={0,255,0,255,0,255}; 
  22. float *HistogramRange[3]={&HistogramRange1[0],&HistogramRange1[2],&HistogramRange1[4]}; 
  23.  
  24. void Print3DHistogram(CvHistogram *Histogram,int BlockSize); 
  25.  
  26. int main() 
  27.      CvHistogram *Histogram1; 
  28.      IplImage *Image1=cvLoadImage("D://image test c++//histrogm3/1.bmp",1); 
  29.      IplImage *RedImage=cvCreateImage(cvGetSize(Image1),8,1); 
  30.      IplImage *GreenImage=cvCreateImage(cvGetSize(Image1),8,1); 
  31.      IplImage *BlueImage=cvCreateImage(cvGetSize(Image1),8,1); 
  32.      IplImage *ImageArray[3]={RedImage,GreenImage,BlueImage}; 
  33.  
  34.      cvSplit(Image1,BlueImage,GreenImage,RedImage,0); 
  35.      Histogram1 = cvCreateHist(3,Histogram3DBlock,CV_HIST_SPARSE,HistogramRange); 
  36.  
  37.      cvCalcHist(ImageArray,Histogram1); 
  38.  
  39.      printf("3D Historgram Data\n"); 
  40.      Print3DHistogram(Histogram1,256); 
  41.  
  42.      cvNamedWindow("Riverbank",1); 
  43.      cvShowImage("Riverbank",Image1); 
  44.  
  45.      cvWaitKey(0); 
  46.  
  47. void Print3DHistogram(CvHistogram *Histogram,int BlockSize) 
  48.     for(int i=0;i<BlockSize;i++) 
  49.      { 
  50.         for(int j=0;j<BlockSize;j++) 
  51.          { 
  52.             for(int k=0;k<BlockSize;k++) 
  53.              { 
  54.                 if(cvQueryHistValue_3D(Histogram,i,j,k)>10) 
  55.                  { 
  56.                      printf("%5.f",cvQueryHistValue_3D(Histogram,i,j,k)); 
  57.                  } 
  58.              } 
  59.          } 
  60.      } 

執行結果:

上面是三個維度的統計直方圖,分別為R維度,G維度,B維度,並且分別被量化成256等分的區塊,同樣的,也是使用LUT的方法,由於這個統計直方圖非常的大,它所佔的區域為256*256*256的大小,而實際上累積的分佈只有一點點,所以說,對於高維度的統計直方圖就要用到稀疏矩陣,要不然會浪放大量的記憶體空間,但是對於多維度的圖表呈現,OpenCV最多也只能支援到一維的方式,二維的方式可以用OpenGL(glut)呈現,當然高的維度本來就很難用視覺化的方式呈現.

cvCreateHist()
初始化CvHistogram資料結構,可以選擇密集矩陣(CvMatND)CV_HIST_ARRAY以及稀疏矩陣(CvSparseMat)CV_HIST_SPARSE,第一個引數為維度的選擇,第二個引數為要將直方圖切割為多少區塊,第三個引數為選擇cvCreateHist()函數的參數或代號,第四個引數為每一個維度的上下界
cvCreateHist(輸入int型別直方圖維度,輸入int型別直方圖區塊數,輸入參數或代號,輸入每個維度的上下界數據)

cvCalcHist()
計算直方圖累積數據,第一個引數為輸入目標IplImage圖形陣列資料結構,第二個引數輸出為CvHistogram資料結構
cvCalcHist(輸入目標IplImage圖形陣列資料結構,輸出為CvHistogram資料結構)

原文:http://www.cnblogs.com/chengmin/archive/2010/03/27/1698219.html

(chengmin)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201004/9184.html]
本文出处:博客园 作者:chengmin
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容