2009年7月27日 星期一
2009年7月20日 星期一
2009年7月14日 星期二
0715
#include
#include
#include
int main()
{
//TODO:Add your command handler code here
IplImage *img=NULL;
int hist_size = 255; //直方圖的計數
float range_0[] = {0,256}; //第0維陣列的變化範圍
float * ranges[] = {range_0};//第1維陣列的變化範圍
int i,bin_w; //下稱號
float max_value = 0 , min_value = 0;//直方圖數值的max和min
int min_idx = 0 , max_idx = 0;//對應上述max和min數值時的下稱號
double mean = 0 , variance = 0;//用於存放平均值(mean)和變化量(variance)的變化
IplImage *pImage=NULL; //聲明IplImage變量
IplImage *pImgGray=NULL;//聲明IplImage變量
//將已讀入系統的圖像複製一份
img=cvLoadImage("lena.jpg");
pImage = img;
//建立和原始圖像一樣的圖像內存區,圖像元素的位深度設為IPL_DEPTH_8U
pImgGray = cvCreateImage(cvSize(pImage->width,pImage->height),IPL_DEPTH_8U,1);
//轉換成灰度圖像
cvCvtColor(pImage,pImgGray,CV_BGR2GRAY);
//創建一個矩形區域
CvRect rect = cvRect(0,0,500,600);
//把矩形作用於圖像以建立一個感興趣區(region of interest,ROI)
cvSetImageROI(pImgGray, rect); //設置ROI
//創建一個圖像用來存放直方圖
IplImage * histImage = cvCreateImage(cvSize(320,200),8,1);
//創建一個指定尺寸的直方圖,用於存放從圖像獲得的信息
CvHistogram * hist = cvCreateHist(1,&hist_size,CV_HIST_ARRAY,ranges,1);
//計算直方圖並作用到hist變量
cvCalcHist(&pImgGray,hist,0,NULL);
//得到直方圖中的最大最小值及其稱號
cvGetMinMaxHistValue(hist,&min_value,&max_value,&min_idx,&max_idx);
//縮放這些最大最小值以內容入圖像內
cvScale(hist->bins,hist->bins,((double)histImage->height)/max_value,0);
//設所有直方圖的數值為255
cvSet(histImage,cvScalarAll(255),0);
//建立一個比例因子以沿寬度縮放
bin_w = cvRound((double)histImage->width/hist_size);
for(i=0;i
cvRectangle(histImage,cvPoint(i*bin_w,histImage->height),cvPoint((i+1)*bin_w,
histImage->height-cvRound(cvGetReal1D(hist->bins,i))),cvScalarAll(0),-1,8,0);
//得到當前數直
float * bins = cvGetHistValue_1D(hist,i);
//增加均數
mean +=bins[0];
//std::cout<
//均值計算完畢
mean /=hist_size;
//有了數值後就可以計算變化量了(variance)
for(i=0;i
variance += pow((bins[0]-mean),2);
}
//變化量計算完畢
variance /=hist_size;
//std::cout<<"Histogram Mean: "<
cvNamedWindow("Original",0); //命名
cvShowImage("Original",pImage); //顯示
cvNamedWindow("Gray",0); //命名
cvShowImage("Gray",pImgGray); //顯示
cvNamedWindow("Histogram",0); //命名
cvShowImage("Histogram",histImage); //顯示
CvFont * pfont = new CvFont;
cvInitFont(pfont,CV_FONT_HERSHEY_SIMPLEX,0.8f,0.8f,0,2);
// CString Result= "Histogram Mean: ";
// CString str;
// str.Format("%f",mean);
// Result +=str + "\n";
// cvPutText(histImage,Result,cvPoint(80,80),pfont,CV_RGB(255 ,0,0));
delete pfont;
//等待按鍵
cvWaitKey(0);
//將程序開始定義的變量釋放
cvReleaseImage(&histImage);
cvReleaseImage(&pImgGray);
//銷毀窗口
cvDestroyWindow("Original");
cvDestroyWindow("Gray");
cvDestroyWindow("Histogram");
}
/*
int main()
{
CMainFrame CM;
OnHistorgram();
}
*/
問題是很簡單的一句...
不知道為什麼不能RUN
6_8程式
6_8主要是做影像處理的四個基本運算
四個運算分別是:腐蝕,膨脹,開運算(先腐蝕再膨脹),閉運算(先膨脹再腐蝕)
以下為完整程式碼(附註解)
#include "cxcore.h"
#include "highgui.h"
#include "cv.h"
class CMainFrame
{
IplImage *img;
public:
CMainFrame()
{
img=cvLoadImage("lena.jpg"); //讀圖並存入參數img
}
void OnErosion();
void OnOpen();
};
void CMainFrame::OnErosion()
{
IplImage *pImgErode = NULL;
IplImage *pImgDilate = NULL;
//將已讀入系統的圖片複製
pImgErode = cvCloneImage(img);
pImgDilate = cvCloneImage(img);
//對輸入圖像使用默認的3X3長方型結構元素進行腐蝕(侵蝕)
cvErode(pImgErode,pImgErode,0,5);
/*cvErode(輸入圖像,輸出圖像,element,腐蝕的次數);
element用於腐蝕的結構元素。若為 NULL, 則使用 3×3 長方形的結構元素
*/
//對輸入圖像使用默認的3X3長方型結構元素進行腐膨脹(擴張)
cvDilate(pImgDilate,pImgDilate,0,5);
/*cvDilate(輸入圖像,輸出圖像,element,膨脹的次數);
element用於膨脹的結構元素。若為 NULL, 則使用 3×3 長方形的結構元素
*/
//建立窗口並顯示圖像
cvNamedWindow("Erosion",0);
cvShowImage("Erosion",pImgErode);
cvNamedWindow("Dilation",0);
cvShowImage("Dilation",pImgDilate);
cvWaitKey(0);
//將程序開始定義的變量釋放
cvReleaseImage(&pImgErode);
cvReleaseImage(&pImgDilate);
//銷毀窗口
cvDestroyWindow("Erosion");
cvDestroyWindow("Dilation");
}
void CMainFrame::OnOpen()
{
IplImage *pImgOpen = NULL;
IplImage *pImgClose = NULL;
IplConvKernel * pKernel = NULL;
//將已讀入系統的圖片複製
pImgOpen = cvCloneImage(img);
pImgClose = cvCloneImage(img);
//創建結構元素
pKernel = cvCreateStructuringElementEx(15,15,8,8,CV_SHAPE_ELLIPSE,NULL);
/*cvCSEE(結構元素的列數目,結構元素的行數目,錨點的相對水平偏移量,錨點的相對垂直偏移量,結構元素的形狀,指向結構元素的指針)
CV_SHAPE_RECT, 長方形元素;
CV_SHAPE_ELLIPSE, 橢圓元素;
CV_SHAPE_CUSTOM, 用戶自定義元素;
指向結構元素的指針,它是一個平面數組,表示對元素矩陣逐行掃描。
(非零點表示該點屬於結構元)。
如果指針為空,則表示平面數組中的所有元素都是非零的,即結構元是一個長方形
(該參數僅僅當shape參數是 CV_SHAPE_CUSTOM 時才予以考慮)
*/
//進行開運算(先腐蝕再膨脹)
cvErode(pImgOpen,pImgOpen,pKernel,1);
cvDilate(pImgOpen,pImgOpen,pKernel,1);
//進行閉運算(先膨脹再腐蝕)
cvDilate(pImgClose,pImgClose,pKernel,1);
cvErode(pImgClose,pImgClose,pKernel,1);
//建立窗口並顯示圖像
cvNamedWindow("Open",0);
cvShowImage("Open",pImgOpen);
cvNamedWindow("Close",0);
cvShowImage("Close",pImgClose);
cvWaitKey(0);
//將程序開始定義的變量釋放
cvReleaseImage(&pImgOpen);
cvReleaseImage(&pImgClose);
//銷毀窗口
cvDestroyWindow("Open");
cvDestroyWindow("Close");
}
int main()
{
CMainFrame CM;
CM.OnErosion();
CM.OnOpen();;
}
所使用過的CV函式:
1.cvCloneImage(輸入圖像)
2.cvErode(輸入圖像,輸出圖像,腐蝕的結構元素,腐蝕的次數)
3.cvDilate(輸入圖像,輸出圖像,膨脹的結構元素,膨脹的次數);
4.cvCreateStructuringElementEx(結構元素的列數目,結構元素的行數目,錨點的相對水平偏移量,錨點的相對垂直偏移量,結構元素的形狀,指向結構元素的指針)
提問:
1.腐蝕跟膨脹的element如果是NULL,在程式執行中,3x3的結構元素是指以一個點的像素與鄰近的上下左右八個點的像素形成的九宮格嗎?
2.延續上一點,腐蝕跟膨脹的函式是將九宮格內的所有值如何做運算的?(課本上這邊相當不容易懂,網路上目前還我還查不到詳細的說明)
3.程式中創建的結構元素pKernel,是使用CV_SHAPE_ELLIPSE橢圓元素,這個對於開運算跟閉運算來講,腐蝕跟膨脹的過程是否即改為使用橢圓的範圍,而不是原來所使用的3x3長方形結構元素?
程式執行心得:
看懂程式碼似乎已經不是最難的過程,拿到這段程式碼之後,最難下手的地方在於怎麼讓它成功的執行出來,對於使用class還不是很敏感,剛開始執行的時候不懂得使用class來宣告,這次的作業當中,除了進一步與CV了解,另外一個最大的收穫就是了解到一路學習程式到現在,卻不會使用最重要的功能”物件”。
HW6-6
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
#include "stdio.h"
#include "iostream"
int main()
{
IplImage* img = 0;
IplImage * pImage = NULL; //宣告一個空間
IplImage * pImg8u = NULL; //宣告一個空間
CvMemStorage * storage = NULL;//宣告一空間來儲存測到的線段
CvSeq * circles = NULL;
img=cvLoadImage("123.jpg");//將圖片讀入img
pImage = cvCloneImage(img);
pImg8u = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);
//轉成灰階圖像
if(img->nChannels != 1)
cvCvtColor(pImage,pImg8u,CV_BGR2GRAY);
else
cvCopy(pImage,pImg8u);
//將圖片平滑化
cvSmooth(pImg8u,pImg8u,CV_GAUSSIAN,7,7);
//創建內存存儲空間(默認值為0表示儲存空間是64k)
storage = cvCreateMemStorage(0);
//找出圖中的圓
circles = cvHoughCircles(pImg8u,storage,CV_HOUGH_GRADIENT,2,pImg8u->height/4,250,55);
int i;
for(i=0;i
{
float * p = (float *)cvGetSeqElem(circles,i);
//依據所給的圓心和半徑來做話元或填充圓的指令
cvCircle(pImage,cvPoint(cvRound(p[0]),cvRound(p[1])),cvRound(p[2]),CV_RGB(255,0,0),3,8,0);//後面代表圓的半徑,顏色,線寬,線型,段數
}
//建立視窗
cvNamedWindow("Houg Circle Transform",1);
//顯示視窗
cvShowImage("Houg Circle Transform",pImage);
//等待按鍵
cvWaitKey(0);
//刪除視窗
cvDestroyWindow("Houg Circle Transform");
cvReleaseImage(& pImage);//釋放圖片
cvReleaseImage(& pImg8u);//釋放圖片
}
所用之函數:
CvMemStorage *cvCreateMemStorage(int block_size=0);
->創造內存儲存空間 裡面宣告的參數,設為0表示儲存空間為64k.
Void cvCircle(CvArr * img,CvPoint center,int radious,CvScalarcolor,int thickness==1,int
Line_type==8,int shift==0);
->在所選擇的圖像上,依據所給的圓心和半徑來對圖形作畫圓或填充圓.
HW6-5
#include
#include
int main()
{
IplImage * img = NULL; // 建立 IplImage 指標變數 img 並且設值為 NULL
IplImage* pImage = NULL; // 建立 IplImage 指標變數 pImage 並且設值為 NULL
IplImage* pImg8u = NULL; // 建立 IplImage 指標變數 pImg8u 並且設值為 NULL ,用於圖像格式轉換
IplImage* pImgCanny = NULL; // 建立 IplImage 指標變數 pImgCanny 並且設值為 NULL ,用於灰度圖像Canny變換
CvMemStorage* storage = NULL; // 建立 CvMemStorage 指標變數 storage 並且設值為 NULL ,用於儲存偵測到的線段
CvSeq* lines = NULL; // 建立 CvSeq 指標變數 lines 並且設值為 NULL ,用於儲存直線的輪廓
img=cvLoadImage("img.jpg"); //將圖片img讀入
pImage = cvCloneImage(img); //將已讀入系統的圖像img複製兩份,一份為背景圖像
pImg8u = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1); //建立一個大小與pImage相等且深度為8的圖 <無符號>
pImgCanny = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1); //建立一個大小與pImage相等且深度為8的圖 <無符號>
cvCvtColor(pImage,pImg8u,CV_BGR2GRAY); //將彩色圖像轉換為灰色圖像
storage = cvCreateMemStorage(0); //建立內存空間
cvCanny(pImg8u,pImgCanny,50,500,3); // 利用Canny變換找出圖像邊緣
lines = cvHoughLines2(pImgCanny,storage,CV_HOUGH_PROBABILISTIC,1,CV_PI/180,80,30,10); // Hough線變換
//在原圖上畫紅直線
for(int i=0 ; i
{
CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
cvLine(pImage,line[0],line[1],CV_RGB(255,0,0),3,8);
}
cvNamedWindow("Hough Line Transform",1); //建立窗口
cvShowImage("Hough Line Transform",pImage); //顯示圖像
cvWaitKey(0); //等待按鍵
cvDestroyWindow("Hough Line Transform"); // 銷毀窗口
cvReleaseImage(&pImage); //將 pImage 程式一開始定義的變量釋放
cvReleaseImage(&pImgCanny); //將 pImgCanny 程序一開始定義的變量釋放
cvReleaseImage(&pImg8u); //將 pImg8u 程序一開始定義的變量釋放
}
原理
Hough變換的原理是利用圖像空間與參數空間的對應關係,將圖像空間的具有一定關係的像素進行聚類,利用某一解析形式轉化到參數空間,通過在參數空間進行簡單的累加統計來完成檢測任務。
Hough直線變換是利用點-線的對偶性。如
由於X-Y座標中的垂直線的k值為無窮大,計算不便,故使用點-正弦函數線對偶變換解決這一問題。
Ρ = x * cos(α) + y * sin(α)
在極座標α-Ρ中變為一條正弦曲線,α取( 0 ~ 180度 )。
6-5的程式主要是Hough直線變換,所偵測到之直線,就將其變換為紅色直線;我們看程式執行的圖與原圖,直線都變為紅色,圓形則不變。
所使用OpenCV相關函數
1. cvHoughLines2 :利用Hough變換在二值圖像中找到直線。
2. cvCreatMemStorage:創建內存存儲空間。
3. cvHoughCircles:利用Hough變換在二值圖像中找到圓。
4. cvLine:在輸入圖像上指定兩點間畫線。
5. cvCircle:在輸入圖像上,根據給定的圓心和半徑畫圓或填充圓。
6. cvCloneImage:複製圖像,包括头,ROI (Region Of Interesting)和數據。
7. cvCreatImage:創建圖並分配數據。
8. cvCvtColor:將彩色圖像轉換成其他顏色之圖像。
cvCvtColor(pImage,pImg8u,CV_BGR2GRAY)
9. cvCanny:利用Canny算法發現輸入圖像的邊緣而且在輸出圖像中標識這些
邊緣。threshold1和threshold2當中的小域值是控制邊緣連接,大
域值用來控制強邊緣的初始分割。
10. cvNamedWindow:建立一個放置圖像和trackbar的窗口。
11. cvShowImage:在指定的窗口顯示圖像。
12. cvWaitKey:使程序等待幾毫秒,讓窗口完成重繪在執行其他操作。
13. cvDestoryWindow:銷毀指定名字的窗口。
14. cvReleaseImage:銷毀已定義的IplImage指針變量,釋放佔用的內存空間。
HW06-2
#include
#include
int main()
{
//宣告變數
IplImage * img = 0;
img=cvLoadImage("img.jpg");
IplImage * pImage = NULL;
IplImage * pImgLaplace = NULL;
IplImage * pImg8u = NULL;
IplImage * pImg8uSmooth = NULL;
//將以讀入系統的圖像複製一份
pImage = cvCloneImage(img);
//建立和原始圖像一樣的圖像內存區,圖像元素的位深度設為IPL_DEPTH_8U
pImg8u = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);
pImg8uSmooth = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);
//將圖像轉換成灰度圖像
cvCvtColor(pImage,pImg8u,CV_BGR2GRAY);
//對灰度圖像進行高斯濾波
cvSmooth(pImg8u,pImg8uSmooth,CV_GAUSSIAN,3,0,0);
//此函數和cvSobel函數一樣要求目標圖像必須是16bit圖像
//如果給8bit目標圖像會報錯
pImgLaplace = cvCreateImage(cvGetSize(img),IPL_DEPTH_16S,1);
cvLaplace(pImg8uSmooth,pImgLaplace,3);
//將圖像格式再轉換回來,用於顯示
cvConvertScaleAbs(pImgLaplace,pImg8u,1,0);
//創建窗口
cvvNamedWindow("laplace gray Image",1);
//顯示圖像
cvvShowImage("laplace gray Image",pImg8u);
//等待按鍵
cvWaitKey(0);
//銷毀窗口
cvDestroyWindow("laplace gray Image");
//將程式開始時所使用的變數釋放
cvReleaseImage(& pImage);
cvReleaseImage(& pImgLaplace);
cvReleaseImage(& pImg8u);
cvReleaseImage(& pImg8uSmooth);
}
主要是先用高斯函數將圖像平滑化,然後再用Laplace進行運算