1、視窗管理
//建立和定位新視窗
cvNamedWindow("win1", CV_WINDOW_AUTOSIZE);
cvMoveWindow("win1", 100, 100); // offset from the UL corner of the screen
//載入映像
IplImage* img=0;
img=cvLoadImage(fileName, CV_LOAD_IMAGE_COLOR);
if(!img)
printf("Could not load image file: %s\n",fileName);
//顯示映像
cvShowImage("win1",img);
//關閉視窗
cvDestroyWindow("win1");
//改變視窗大小
cvResizeWindow("win1",100,100); // new width/heigh in pixels
2、輸入處理處理滑鼠事件
//先定義滑鼠處理常式
//x,y相對於左上方的像素座標
void mouseHandler(int event, int x, int y, int flags, void* param)
{
switch(event)
{
case CV_EVENT_LBUTTONDOWN:
if(flags & CV_EVENT_FLAG_CTRLKEY)
printf("Left button down with CTRL pressed\n");
break;
case CV_EVENT_LBUTTONUP:
printf("Left button up\n");
break;
}
}
//再註冊該事件處理常式
mouseParam=5;
cvSetMouseCallback("win1",mouseHandler,&mouseParam); //第三個參數可以設定為NULL
處理鍵盤事件
//按一定間隔檢測鍵盤輸入
int key;
key=cvWaitKey(10); // wait 10ms for input
//中止程式等待鍵盤輸入
int key;
key=cvWaitKey(0); // wait indefinitely for input
//鍵盤輸入迴圈處理常式
while(1)
{
key=cvWaitKey(10);
if(key==27) break;
switch(key)
{
case 'h':
...
break;
case 'i':
...
break;
}
}
處理滑動條事件
//定義一個滑動條處理常式
void trackbarHandler(int pos)
{
printf("Trackbar position: %d\n",pos);
}
//註冊該事件處理常式
int trackbarVal=25;
int maxVal=100;
cvCreateTrackbar("bar1", "win1", &trackbarVal ,maxVal , trackbarHandler);
//擷取當前的滑動條位置
int pos = cvGetTrackbarPos("bar1","win1");
//設定滑動條位置
cvSetTrackbarPos("bar1", "win1", 25);
3、影像處理
映像的記憶體配置與釋放
//分配記憶體給一幅新映像
//size:cvSize(width,height);depth: 像素深度;channels: 像素通道數. Can be 1, 2, 3 or 4.
IplImage* cvCreateImage(CvSize size, int depth, int channels);
// Allocate a 1-channel byte image
IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
// Allocate a 3-channel float image
IplImage* img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
//釋放映像
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
cvReleaseImage(&img);
//複製映像
IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
IplImage* img2;
img2=cvCloneImage(img1); // 注意通過cvCloneImage得到的映像
// 也要用 cvReleaseImage 釋放,否則容易產生記憶體流失
//設定/擷取感興趣地區ROI
void cvSetImageROI(IplImage* image, CvRect rect);
void cvResetImageROI(IplImage* image);
CvRect cvGetImageROI(const IplImage* image);
// 設定/擷取感興趣通道COI
void cvSetImageCOI(IplImage* image, int coi); // 0=all
int cvGetImageCOI(const IplImage* image);
映像讀寫
//從檔案中讀入映像
//OpenCV預設將讀入的映像強制轉換為一幅三通道彩色映像
IplImage* img=0;
img=cvLoadImage(fileName);
if(!img)
printf("Could not load image file: %s\n",fileName);
img=cvLoadImage(fileName,flag);
// flag: >0 將讀入的映像強制轉換為一幅三通道彩色映像
// =0 將讀入的映像強制轉換為一幅單通道灰階映像
// <0 讀入的映像通道數與所讀入的檔案相同.
//儲存映像
if(!cvSaveImage(outFileName,img))
printf("Could not save: %s\n", outFileName);
訪問映像像素
間接訪問,效率低
//對於單通道位元組型映像
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
CvScalar s;
s=cvGet2D(img,i,j); // get the (j,i) pixel value, 注意cvGet2D與cvSet2D中座標參數的順序與其它opencv函數座標參數順序恰好相反.本函數中i代表y軸,即height;j代表x軸,即weight.
printf("intensity=%f\n",s.val[0]);
s.val[0]=111;
cvSet2D(img,i,j,s); // set the (j,i) pixel value
//對於多通道位元組型/浮點型映像
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
CvScalar s;
s=cvGet2D(img,i,j); // get the (j,i) pixel value
printf("B=%f, G=%f, R=%f\n",s.val[0],s.val[1],s.val[2]);
s.val[0]=111;
s.val[1]=111;
s.val[2]=111;
cvSet2D(img,i,j,s); // set the (j,i) pixel value
直接存取,效率高
//對於單通道位元組型映像
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
((uchar *)(img->imageData + i*img->widthStep))[j]=111;
//對於多通道位元組型映像
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
//對於多通道浮點型映像
IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
基於指標的直接存取
//對於單通道位元組型映像
IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
int height = img->height;
int width = img->width;
int step = img->widthStep;
uchar* data = (uchar *)img->imageData;
data[i*step+j] = 111;
//對於多通道位元組型映像
IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
int height = img->height;
int width = img->width;
int step = img->widthStep;
int channels = img->nChannels;
uchar* data = (uchar *)img->imageData;
data[i*step+j*channels+k] = 111;
映像轉換
//位元組型映像的灰階-彩色轉換:
cvConvertImage(src, dst, flags=0);
src = float/byte grayscale/color image
dst = byte grayscale/color image
flags = CV_CVTIMG_FLIP (垂直翻轉映像)
CV_CVTIMG_SWAP_RB (置換 R 和 B 通道)
//彩色映像->灰階映像:
// Using the OpenCV conversion:
cvCvtColor(cimg,gimg,CV_BGR2GRAY); // cimg -> gimg
// Using a direct conversion:
for(i=0;i<cimg->height;i++) for(j=0;j<cimg->width;j++)
gimgA[i][j]= (uchar)(cimgA[i][j].b*0.114 +
cimgA[i][j].g*0.587 +
cimgA[i][j].r*0.299);
//不同彩色空間之間的轉換:
cvCvtColor(src,dst,code); // src -> dst
code = CV_<X>2<Y>
<X>/<Y> = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS
繪圖指令
//繪製矩形:
// 在點 (100,100) 和 (200,200) 之間繪製一矩形,邊線用紅色、寬度為 1
cvRectangle(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,0,255), 1);
//繪製圓形:
// 圓心為(100,100)、半徑為20. 圓周綠色、寬度為1
cvCircle(img, cvPoint(100,100), 20, cvScalar(0,255,0), 1);
//繪製線段:
// 在 (100,100) 和 (200,200) 之間、線寬為 1 的綠色線段
cvLine(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,255,0), 1);
//繪製一組線段:
CvPoint curve1[]={10,10, 10,100, 100,100, 100,10};
CvPoint curve2[]={30,30, 30,130, 130,130, 130,30, 150,10};
CvPoint* curveArr[2]={curve1, curve2};
int nCurvePts[2]={4,5};
int nCurves=2;
int isCurveClosed=1;
int lineWidth=1;
cvPolyLine(img,curveArr,nCurvePts,nCurves,isCurveClosed,cvScalar(0,255,255),lineWidth);
void cvPolyLine( CvArr* img, CvPoint** pts, int* npts, int contours, int is_closed,
CvScalar color, int thickness=1, int line_type=8, int shift=0 );
//img 映像。
//pts 折線的頂點指標數組。
//npts 折線的定點個數數組。也可以認為是pts指標數組的大小
//contours 折線的線段數量。
//is_closed 指出多邊形是否封閉。如果封閉,函數將起始點和結束點連線。
//color 折線的顏色。
//thickness 線條的粗細程度。
//line_type 線段的類型。參見cvLine。
//shift 頂點的小數點位元
//繪製一組填充顏色的多邊形:
cvFillPoly(img,curveArr,nCurvePts,nCurves,cvScalar(0,255,255));
//cvFillPoly用於一個單獨被多邊形輪廓所限定的地區內進行填充。函數可以填充複雜的地區,例如,有漏洞的地區和有交叉點的地區等等。
void cvFillPoly( CvArr* img, CvPoint** pts, int* npts, int contours,CvScalar color, int line_type=8, int shift=0 );
//img 映像。
//pts 指向多邊形的數組指標。
//npts 多邊形的頂點個數的數組。
//contours 組成填充地區的線段的數量。
//color 多邊形的顏色。
//line_type 組成多邊形的線條的類型。
//shift 頂點座標的小數點位元。
//文本標註:
CvFont font;
double hScale=1.0;
double vScale=1.0;
int lineWidth=1;
cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC, hScale,vScale,0,lineWidth);
cvPutText (img,"My comment",cvPoint(200,400), &font, cvScalar(255,255,0));
4、視頻處理
//初始化一個相機擷取器:
CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0
//初始化一個視頻檔案捕捉器:
CvCapture* capture = cvCaptureFromAVI("infile.avi");
//捕捉一幀畫面:
IplImage* img = 0;
if(!cvGrabFrame(capture)) // capture a frame
{
printf("Could not grab a frame\n\7");
exit(0);
}
img=cvRetrieveFrame(capture); // retrieve the captured frame
//釋放視頻流捕捉器:
cvReleaseCapture(&capture);
//擷取視頻流裝置資訊:
cvQueryFrame(capture); // 在讀取視頻流資訊前,要先執行此操作
int frameH = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
int frameW = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
int fps = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
int numFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
//擷取幀圖資訊:
float posMsec = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC);
int posFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES);
float posRatio = cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO);
//設定從視頻檔案抓取的第一幀畫面的位置:
// start capturing from a relative position of 0.9 of a video file
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO, (double)0.9);
//初始化視頻編寫器:
CvVideoWriter *writer = 0;
int isColor = 1;
int fps = 25; // or 30
int frameW = 640; // 744 for firewire cameras
int frameH = 480; // 480 for firewire cameras
writer=cvCreateVideoWriter("out.avi",CV_FOURCC('P','I','M','1'),
fps,cvSize(frameW,frameH),isColor);
//保持視頻檔案:
IplImage* img = 0;
int nFrames = 50;
for(i=0;i<nFrames;i++){
cvGrabFrame(capture); // capture a frame
img=cvRetrieveFrame(capture); // retrieve the captured frame
// img = cvQueryFrame(capture);
cvWriteFrame(writer,img); // add the frame to the file
}
//釋放視頻編寫器:
cvReleaseVideoWriter(&writer);