1. 程式人生 > >影象處理經典演算法及OpenCV程式

影象處理經典演算法及OpenCV程式

基於opencv的use攝像頭視訊採集程式

準備工作:你得把opencv庫裝到電腦上,並把各種標頭檔案,原始檔,lib庫都連到vc上,然後設定一下系統環境變數,這裡這方面就不說了,好像我前面的文章有說過,不懂也可百度一下。

建立一個基於WIN32控制檯的工程CameraUSB,在新建一個c++元檔案,寫程式碼:

#include "cxcore.h" #include "cvcam.h" #include "windows.h" #include "highgui.h"

void callback(IplImage* image); int main() { int ncams=cvcamGetCamerasCount( );//返回可以訪問的攝像頭數目 HWND MyWin;     // 設定系統屬性 cvcamSetProperty(0, CVCAM_PROP_ENABLE, CVCAMTRUE); //選擇第一個攝像頭   //camera     cvcamSetProperty(0, CVCAM_PROP_RENDER, CVCAMTRUE); //We'll render stream     // 在本例中     // 假設建立一個視窗,並且視窗的ID是在變數 MyWin 中定義     // MyWin 是視窗 HWND 的型別     MyWin=(HWND)cvGetWindowHandle("CameraUSB window");       cvcamSetProperty(0,CVCAM_PROP_WINDOW,&MyWin);   // Selects a window for     //video rendering //回撥函式將處理每一幀 cvcamSetProperty(0,CVCAM_PROP_CALLBACK,callback);      cvcamInit( );     cvcamStart( );     // 現在程式開始工作     cvWaitKey(0);     cvcamStop( );     cvcamExit( );     return 0; }

// 在影象中畫蘭色水平線 void callback(IplImage* image) {     IplImage* image1 = image;     int i,j;         assert (image);         for(i=0; i<image1->height; i+=10)     {         for(j=(image1->widthStep)*i; j<(image1->widthStep)*(i+1);         j+=image1->nChannels)         {             image1->imageData[j]   = (char)255;             image1->imageData[j+1] = 0;             image1->imageData[j+2] = 0;         }      } }

嘿嘿,就這麼簡單就完事了。

不懂可留言問

實現功能:同時採集兩路USB攝像頭資料,並顯示,具有圖片儲存功能(點選左鍵儲存圖片,並暫停視訊;右鍵繼續視訊)。步驟就不說了,很簡單,直接放程式碼了:

#include <cvcam.h> #include <cv.h> #include <highgui.h> #include "stdio.h" #include <windows.h>

void StereoCallback(IplImage *frame1,IplImage *frame2); void onMouse1(int Event,int x,int y,int flags,void *param); void onMouse2(int Event,int x,int y,int flags,void *param);

IplImage *image1,*image2;

char *strleft[4]={"left1.bmp","left2.bmp","left3.bmp","left4.bmp"}; char *strright[4]={"right1.bmp","right2.bmp","right3.bmp","right4.bmp"};

void main() {     HWND CaptureWindow1=0; //不賦值也行     HWND CaptureWindow2=0;

//int ncams=cvcamGetCamerasCount(); //獲取攝像頭的個數,在這裡可有可無 //用對話方塊的形式來選取攝像頭     int *CameraNumber;     int nSelected = cvcamSelectCamera(&CameraNumber);

/* //灰色影象 image1=cvCreateImage(cvSize(320,240),IPL_DEPTH_8U,1); image2=cvCreateImage(cvSize(320,240),IPL_DEPTH_8U,1); */

//彩色影象 image1=cvCreateImage(cvSize(320,240),IPL_DEPTH_8U,3); image2=cvCreateImage(cvSize(320,240),IPL_DEPTH_8U,3);

//初始化兩個攝像頭    cvNamedWindow("cvcam1 Window",1);         CaptureWindow1=(HWND)cvGetWindowHandle("cvcam1 Window");         cvcamSetProperty(CameraNumber[0], CVCAM_PROP_ENABLE, CVCAMTRUE);         cvcamSetProperty(CameraNumber[0], CVCAM_PROP_RENDER, CVCAMTRUE);         cvcamSetProperty(CameraNumber[0], CVCAM_PROP_WINDOW, &CaptureWindow1); // cvSetMouseCallback("cvcam1 Window",onMouse1,0);         cvNamedWindow("cvcam2 Window",1);         CaptureWindow2=(HWND)cvGetWindowHandle("cvcam2 Window");         cvcamSetProperty(CameraNumber[1], CVCAM_PROP_ENABLE, CVCAMTRUE);         cvcamSetProperty(CameraNumber[1], CVCAM_PROP_RENDER, CVCAMTRUE);         cvcamSetProperty(CameraNumber[1], CVCAM_PROP_WINDOW, &CaptureWindow2); // cvSetMouseCallback("cvcam2 Window",onMouse2,0);

//讓兩個攝像頭同步    cvcamSetProperty(CameraNumber[0],CVCAM_STEREO_CALLBACK,(void*)&StereoCallback);

//啟動程式     cvcamInit();     cvcamStart(); cvSetMouseCallback("cvcam1 Window",onMouse1,0); cvSetMouseCallback("cvcam2 Window",onMouse2,0);     cvWaitKey(0);

    cvcamStop(); free(CameraNumber); cvcamExit();     cvDestroyWindow("cvcam1 Window");     cvDestroyWindow("cvcam2 Window"); }

void StereoCallback(IplImage* frame1,IplImage *frame2) {

/*   //把影象轉換成灰度圖並儲存到image中 cvCvtColor(frame1,image1,CV_RGB2GRAY); cvCvtColor(frame2,image2,CV_RGB2GRAY); */

//拷貝影象到全域性變數image中 該函式這樣用存在問題 // cvCopy(frame1,image1); // cvCopy(frame2,image2); image1=cvCloneImage(frame1); image2=cvCloneImage(frame2); //對擷取的影象翻轉 cvFlip(image1,image1,0); cvFlip(image2,image2,0);

} void onMouse1(int Event,int x,int y,int flags,void *param) { static int num=0;    if(Event==CV_EVENT_LBUTTONDOWN)    {    if(num==4)num=0;//只是固定定義了儲存4張圖片,為了不讓程式非法而設定的復原     cvcamPause();     //影象儲存    cvSaveImage(strleft[num],image1); // cvSaveImage(strright[num],image2);    // cvSaveImage("left.bmp",image1);    // cvSaveImage("right.bmp",image2);

   }    if(Event==CV_EVENT_RBUTTONDOWN)    {     cvcamResume();     num++;    }    }

void onMouse2(int Event,int x,int y,int flags,void *param) { static int num=0;    if(Event==CV_EVENT_LBUTTONDOWN)    {    if(num==4)num=0;//只是固定定義了儲存4張圖片,為了不讓程式非法而設定的復原     cvcamPause();     //影象儲存 //   cvSaveImage(strleft[num],image1);    cvSaveImage(strright[num],image2);    // cvSaveImage("left.bmp",image1);    // cvSaveImage("right.bmp",image2);

   }    if(Event==CV_EVENT_RBUTTONDOWN)    {     cvcamResume();     num++;    }    }

這個程式是基於opencv的,連線庫就不說了,直接建立一個基於win32的控制檯程式,寫程式碼就OK了。

/* 程式名:drawing..c 功能:展示OpenCV的影象繪製功能 */ #include "cv.h" #include "highgui.h" #include <stdlib.h> #include <stdio.h> #define NUMBER 100 #define DELAY 5 char wndname[] = "Drawing Demo";

CvScalar random_color(CvRNG* rng) //函式 cvRNG 初始化隨機數生成器並返回其狀態,RNG 隨機數生成器 {     int icolor = cvRandInt(rng); //函式 cvRandInt 返回均勻分佈的隨機 32-bit 無符號整型值並更新 RNG 狀態     return CV_RGB(icolor&255, (icolor>>8)&255, (icolor>>16)&255); //建立 一個色彩值 }

int main( int argc, char** argv ) {     int line_type = CV_AA; // change it to 8 to see non-antialiased graphics     int i;     CvPoint pt1,pt2; //基於二維整形座標軸的點     double angle;     CvSize sz;   //矩形框大小,以畫素為精度     CvPoint ptt[6];     CvPoint* pt[2];     int arr[2];     CvFont font;     CvRNG rng;     int width = 1000, height = 700;     int width3 = width*3, height3 = height*3;     CvSize text_size;     int ymin = 0;     // Load the source image     IplImage* image = cvCreateImage( cvSize(width,height), 8, 3 );     IplImage* image2;

    // Create a window     cvNamedWindow(wndname, 1 );     cvZero( image ); //#define cvZero cvSetZero   void cvSetZero( CvArr* arr ); arr 要被清空陣列     cvShowImage(wndname,image);

    rng = cvRNG((unsigned)-1);     pt[0] = &(ptt[0]);     pt[1] = &(ptt[3]);

    arr[0] = 3;     arr[1] = 3;

    for (i = 0; i< NUMBER; i++)     {         pt1.x=cvRandInt(&rng) % width3 - width;         pt1.y=cvRandInt(&rng) % height3 - height;         pt2.x=cvRandInt(&rng) % width3 - width;         pt2.y=cvRandInt(&rng) % height3 - height;

        cvLine( image, pt1, pt2, random_color(&rng), cvRandInt(&rng)%10, line_type, 0 );//繪製連線兩個點的線段         cvShowImage(wndname,image);         cvWaitKey(DELAY);     }

    for (i = 0; i< NUMBER; i++)     {         pt1.x=cvRandInt(&rng) % width3 - width;         pt1.y=cvRandInt(&rng) % height3 - height;         pt2.x=cvRandInt(&rng) % width3 - width;         pt2.y=cvRandInt(&rng) % height3 - height;

        cvRectangle( image,pt1, pt2, random_color(&rng), cvRandInt(&rng)%10-1, line_type, 0 );//繪製簡單、指定粗細或者帶填充的 矩形         cvShowImage(wndname,image);         cvWaitKey(DELAY);     }

    for (i = 0; i< NUMBER; i++)     {         pt1.x=cvRandInt(&rng) % width3 - width;         pt1.y=cvRandInt(&rng) % height3 - height;         sz.width =cvRandInt(&rng)%200;         sz.height=cvRandInt(&rng)%200;         angle = (cvRandInt(&rng)%1000)*0.180;

        cvEllipse( image, pt1, sz, angle, angle - 100, angle + 200,                    random_color(&rng), cvRandInt(&rng)%10-1, line_type, 0 );//函式cvEllipse用來繪製或者填充一個簡單的橢圓弧或橢圓扇形         cvShowImage(wndname,image);         cvWaitKey(DELAY);     }

    for (i = 0; i< NUMBER; i++)     {         pt[0][0].x=cvRandInt(&rng) % width3 - width;         pt[0][0].y=cvRandInt(&rng) % height3 - height;         pt[0][1].x=cvRandInt(&rng) % width3 - width;         pt[0][1].y=cvRandInt(&rng) % height3 - height;         pt[0][2].x=cvRandInt(&rng) % width3 - width;         pt[0][2].y=cvRandInt(&rng) % height3 - height;         pt[1][0].x=cvRandInt(&rng) % width3 - width;         pt[1][0].y=cvRandInt(&rng) % height3 - height;         pt[1][1].x=cvRandInt(&rng) % width3 - width;         pt[1][1].y=cvRandInt(&rng) % height3 - height;         pt[1][2].x=cvRandInt(&rng) % width3 - width;         pt[1][2].y=cvRandInt(&rng) % height3 - height;

        cvPolyLine( image, pt, arr, 2, 1, random_color(&rng), cvRandInt(&rng)%10, line_type, 0 );//函式cvPolyLine 繪製一個簡單的或多樣的多角曲線         cvShowImage(wndname,image);         cvWaitKey(DELAY);     }

    for (i = 0; i< NUMBER; i++)     {         pt[0][0].x=cvRandInt(&rng) % width3 - width;         pt[0][0].y=cvRandInt(&rng) % height3 - height;         pt[0][1].x=cvRandInt(&rng) % width3 - width;         pt[0][1].y=cvRandInt(&rng) % height3 - height;         pt[0][2].x=cvRandInt(&rng) % width3 - width;         pt[0][2].y=cvRandInt(&rng) % height3 - height;         pt[1][0].x=cvRandInt(&rng) % width3 - width;         pt[1][0].y=cvRandInt(&rng) % height3 - height;         pt[1][1].x=cvRandInt(&rng) % width3 - width;         pt[1][1].y=cvRandInt(&rng) % height3 - height;         pt[1][2].x=cvRandInt(&rng) % width3 - width;         pt[1][2].y=cvRandInt(&rng) % height3 - height;

        cvFillPoly( image, pt, arr, 2, random_color(&rng), line_type, 0 );//函式cvFillPoly用於一個單獨被多變形輪廓所限定的區域內進行填充         cvShowImage(wndname,image);         cvWaitKey(DELAY);     }

    for (i = 0; i< NUMBER; i++)     {         pt1.x=cvRandInt(&rng) % width3 - width;         pt1.y=cvRandInt(&rng) % height3 - height;

        cvCircle( image, pt1, cvRandInt(&rng)%300, random_color(&rng),                   cvRandInt(&rng)%10-1, line_type, 0 );//函式cvCircle繪製或填充一個給定圓心和半徑的圓         cvShowImage(wndname,image);         cvWaitKey(DELAY);     }

    for (i = 1; i< NUMBER; i++)     {         pt1.x=cvRandInt(&rng) % width3 - width;         pt1.y=cvRandInt(&rng) % height3 - height;

        cvInitFont( &font, cvRandInt(&rng) % 8, (cvRandInt(&rng)%100)*0.05+0.1, (cvRandInt(&rng)%100)*0.05+0.1, (cvRandInt(&rng)%5)*0.1, cvRound(cvRandInt(&rng)%10), line_type );//字型結構初始化。函式 cvRound, cvFloor, cvCeil 用一種舍入方法將輸入浮點數轉換成整數。 cvRound 返回和引數最接近的整數值

        cvPutText( image, "Northeast Petroleum University!", pt1, &font, random_color(&rng));//在影象中加入文字         cvShowImage(wndname,image);         cvWaitKey(DELAY);     }

    cvInitFont( &font, CV_FONT_HERSHEY_COMPLEX, 3, 3, 0.0, 5, line_type );

    cvGetTextSize( "Opencv forever!", &font, &text_size, &ymin );//設定字串文字的寬度和高度

    pt1.x = (width - text_size.width)/2;     pt1.y = (height + text_size.height)/2;     image2 = cvCloneImage(image);

    for( i = 0; i < 255; i++ )     {         cvSubS( image2, cvScalarAll(i), image, 0 );//函式 cvSubS 從原陣列的每個元素中減去一個數量         cvPutText( image, "shentuhongfeng    forever!", pt1, &font, CV_RGB(255,i,i));         cvShowImage(wndname,image);         cvWaitKey(DELAY);     }

    // Wait for a key stroke; the same function arranges events processing     cvWaitKey(0);     cvReleaseImage(&image);     cvReleaseImage(&image2);     cvDestroyWindow(wndname);

return 0; }

效果圖:太帥了

黑的變白了,白的變黑了

原始碼:

#include<stdio.h> #include<math.h> #include<cv.h> #include<highgui.h>

int main(int argc,char* argv[]) { IplImage* img=0; int height,width,step,channels; UCHAR* data; int i,j,k; if(argc<2) {    printf("Usage:InvImage<image-file-name>\n\7");    exit(0); } img=cvLoadImage(argv[1]); if(!img) {    printf("Could not load image file:%s\n",argv[1]);    exit(0); } height=img->height; width=img->width; step=img->widthStep; channels=img->nChannels; data=(UCHAR*)img->imageData; printf("Processing a%d*%d image with %d channels\n",height,width,channels); cvNamedWindow("mainWin",CV_WINDOW_AUTOSIZE); cvMoveWindow("mainWin",100,100);

for(i=0;i<height;i++)    for(j=0;j<width;j++)     for(k=0;k<channels;k++)      data[i*step+j*channels+k]=255-data[i*step+j*channels+k]; cvShowImage("mainWin",img); cvWaitKey(0); cvReleaseImage(&img); return 0; }

首先要準備一張圖片,和幾個txt文件,把txt文件的副檔名改成一個你要把圖片轉換成的格式

我用的原始圖片是jpg的,txt改成bmp的

使用時,執行-cmd-cd 轉到你的目錄- Convert.exe 1.jpg 2.bmp 執行就能把影象1.jpg轉換成2.bmp了

原始碼如下:

/* 程式名:convert.c 功能:影象格式的轉換 */ #include <cv.h> #include <highgui.h> #include <stdio.h> int main( int argc, char** argv ) { IplImage* src; // -1: the loaded image will be loaded as is (with number of channels depends on the file). if(argc != 3) {     printf("CONV: Image format convertion, support JPG,BMP,TIF,PNG,PPM\n");     printf("Usage: conv srcImage dstImage\n");     return 0; } if( ( strstr(argv[1],".jpg")==NULL    && strstr(argv[1],".bmp")==NULL && strstr(argv[1],".tif")==NULL && strstr(argv[1],".png")==NULL && strstr(argv[1],".ppm")==NULL )     || ( strstr(argv[2],".jpg")==NULL && strstr(argv[2],".bmp")==NULL && strstr(argv[2],".tif")==NULL && strstr(argv[2],".png")==NULL && strstr(argv[2],".ppm")==NULL )) //strstr(a, b)的用法是不是在a陣列內檢視是否有b陣列。。。沒有則輸出NULL {     printf("WARNING: CONV only support JPG,BMP,TIF,PPM,TGA and PPM\n");     } else { if( (src=cvLoadImage(argv[1], -1))!= 0 ) {          cvSaveImage( argv[2], src);             cvReleaseImage(&src);             printf("\n Convert successfully.\n");     }     else     {        printf("\n*** Read or write image fails *** \n");     } } return 0; }

發現了個小問題:

原來的jpg影象只有102KB轉換成bmp後變成549KB ,在執行程式把這個bmp轉成jpg又只有81KB。這真是汗死我了

從攝像頭或者AVI檔案中得到視訊流,對視訊流進行邊緣檢測

/* 程式名稱:laplace.c 功能:從攝像頭或者AVI檔案中得到視訊流,對視訊流進行邊緣檢測,並輸出結果。 */ #include "cv.h" #include "highgui.h" #include <ctype.h> #include <stdio.h>

int main( int argc, char** argv ) {     IplImage* laplace = 0;     IplImage* colorlaplace = 0;     IplImage* planes[3] = { 0, 0, 0 }; // 多個影象面     CvCapture* capture = 0;         // 下面的語句說明在命令列執行程式時,如果指定AVI檔案,那麼處理從 // AVI檔案讀取的視訊流,如果不指定輸入變數,那麼處理從攝像頭獲取 // 的視訊流 if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))         capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );     else if( argc == 2 )         capture = cvCaptureFromAVI( argv[1] );

    if( !capture )     {         fprintf(stderr,"Could not initialize capturing...\n");         return -1;     }             cvNamedWindow( "Laplacian", 0 );

// 迴圈捕捉,直到使用者按鍵跳出迴圈體     for(;;)     {         IplImage* frame = 0;         int i;

        frame = cvQueryFrame( capture );         if( !frame )             break;

        if( !laplace )         {             for( i = 0; i < 3; i++ )                 planes[i] = cvCreateImage( cvSize(frame->width,frame->height), 8, 1 ); laplace = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_16S, 1 );             colorlaplace = cvCreateImage( cvSize(frame->width,frame->height), 8, 3 );         }         cvCvtPixToPlane( frame, planes[0], planes[1], planes[2], 0 );         for( i = 0; i < 3; i++ )         {             cvLaplace( planes[i], laplace, 3 ); // 3: aperture_size             cvConvertScaleAbs( laplace, planes[i], 1, 0 ); // planes[] = ABS(laplace)         }         cvCvtPlaneToPix( planes[0], planes[1], planes[2], 0, colorlaplace );         colorlaplace->origin = frame->origin;

        cvShowImage("Laplacian", colorlaplace );

        if( cvWaitKey(10) >= 0 )             break;     }     cvReleaseCapture( &capture );     cvDestroyWindow("Laplacian");     return 0; }

#include "cv.h" #include "highgui.h"

char wndname[] = "Edge"; char tbarname[] = "Threshold"; int edge_thresh = 1;

IplImage *image = 0, *cedge = 0, *gray = 0, *edge = 0;

// 定義跟蹤條的 callback 函式 void on_trackbar(int h) {     cvSmooth( gray, edge, CV_BLUR, 3, 3, 0 );     cvNot( gray, edge );

    // 對灰度影象進行邊緣檢測     cvCanny(gray, edge, (float)edge_thresh, (float)edge_thresh*3, 3);     cvZero( cedge );     // copy edge points     cvCopy( image, cedge, edge );     // 顯示影象     cvShowImage(wndname, cedge); }

int main( int argc, char** argv ) {     char* filename = argc == 2 ? argv[1] : (char*)"fruits.jpg";         if( (image = cvLoadImage( filename, 1)) == 0 )         return -1;

    // Create the output image     cedge = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 3);

    // 將彩色影象轉換為灰度影象     gray = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 1);     edge = cvCreateImage(cvSize(image->width,image->height), IPL_DEPTH_8U, 1);     cvCvtColor(image, gray, CV_BGR2GRAY);

    // Create a window     cvNamedWindow(wndname, 1);

    // create a toolbar     cvCreateTrackbar(tbarname, wndname, &edge_thresh, 100, on_trackbar);

    // Show the image     on_trackbar(1);

    // Wait for a key stroke; the same function arranges events processing     cvWaitKey(0);     cvReleaseImage(&image);     cvReleaseImage(&gray);     cvReleaseImage(&edge);     cvDestroyWindow(wndname);

    return 0; }

/*******程式碼中的函式說明 1、cvSmooth,其函式宣告為: cvSmooth( const void* srcarr, void* dstarr, int smoothtype,int param1, int param2, double param3 ) cvSmooth函式的作用是對圖象做各種方法的圖象平滑。其中,srcarr為輸入圖象;dstarr為輸出圖象; param1為平滑操作的第一個引數;param2為平滑操作的第二個引數(如果param2值為0,則表示它被設為param1); param3是對應高斯引數的標準差。 引數smoothtype是圖象平滑的方法選擇,主要的平滑方法有以下五種: CV_BLUR_NO_SCALE:簡單不帶尺度變換的模糊,即對每個象素在 param1×param2領域求和。 CV_BLUR:對每個象素在param1×param2鄰域求和並做尺度變換 1/(param1?param2)。 CV_GAUSSIAN:對影象進行核大小為param1×param2的高斯卷積。 CV_MEDIAN:對影象進行核大小為param1×param1 的中值濾波(鄰域必須是方的)。 CV_BILATERAL:雙向濾波,應用雙向 3x3 濾波,彩色設定為param1,空間設定為param2。

2、void cvNot(const CvArr* src,CvArr* dst); 函式cvNot()會將src中的每一個元素的每一位取反,然後把結果賦給dst。 因此,一個值為0x00的8點陣圖像將被對映到0xff,而值為0x83的影象將被對映到0x7c。

3、void cvCanny( const CvArr* image, CvArr* edges, double threshold1,double threshold2, int aperture_size=3 ); 採用 Canny 演算法做邊緣檢測 image 輸入影象 edges 輸出的邊緣影象 threshold1 第一個閾值 threshold2 第二個閾值 aperture_size Sobel 運算元核心大小

4、void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL ); 在使用這個函式之前,你必須用cvCreateImage()一類的函式先開一段記憶體,然後傳遞給dst。 cvCopy會把src中的資料複製到dst的記憶體中。

5、cvCreateTrackbar 建立trackbar並將它新增到指定的視窗。 int cvCreateTrackbar( const char* trackbar_name, const char* window_name, int* value, int count, CvTrackbarCallback on_change ); trackbar_name 被建立的trackbar名字。 window_name 視窗名字,這個視窗將為被建立trackbar的父物件。 value 整數指標,它的值將反映滑塊的位置。這個變數指定建立時的滑塊位置。 count 滑塊位置的最大值。最小值一直是0。 on_change 每次滑塊位置被改變的時候,被呼叫函式的指標。這個函式應該被宣告為void Foo(int); 如果沒有回撥函式,這個值可以設為NULL。 函式cvCreateTrackbar用指定的名字和範圍來建立trackbar(滑塊或者範圍控制),指定與trackbar位置同步的變數, 並且指定當trackbar位置被改變的時候呼叫的回撥函式。被建立的trackbar顯示在指定視窗的頂端。 */

角點檢測

原始圖:

處理後圖:

原始碼:

#include <stdio.h> #include "cv.h" #include "highgui.h" #define max_corners 100

int main( int argc, char** argv ) {     int cornerCount=max_corners;     CvPoint2D32f corners[max_corners];     IplImage *srcImage = 0, *grayImage = 0, *corners1 = 0, *corners2 = 0;     int i;     CvScalar color = CV_RGB(255,0,0);     char* filename = argc == 2 ? argv[1] : (char*)"pic3.png"; // 注意相對路徑             cvNamedWindow( "image", 1 ); // create HighGUI window with name "image"         //Load the image to be processed     srcImage = cvLoadImage(filename, 1);         grayImage = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_8U, 1);         //copy the source image to copy image after converting the format     cvCvtColor(srcImage, grayImage, CV_BGR2GRAY);         //create empty images of same size as the copied images     corners1= cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_32F, 1);     corners2= cvCreateImage(cvGetSize(srcImage),IPL_DEPTH_32F, 1);         cvGoodFeaturesToTrack (grayImage, corners1,         corners2, corners,         &cornerCount, 0.05,         5,         0,         3, // block size         0, // not use harris         0.4 );         printf("num corners found: %d\n", cornerCount);         // draw circles at each corner location in the gray image and     //print out a list the corners     if(cornerCount>0)     {         for (i=0; i<cornerCount; i++)         {             cvCircle(srcImage, cvPoint((int)(corners[i].x), (int)(corners[i].y)), 6,                 color, 2, CV_AA, 0);         }     }         cvShowImage( "image", srcImage );         cvReleaseImage(&srcImage);     cvReleaseImage(&grayImage);     cvReleaseImage(&corners1);     cvReleaseImage(&corners2);         cvWaitKey(0); // wait for key. The function has     return 0; }

友情連結一下,這是別人寫的:

#include "cv.h" #include "highgui.h" #include "math.h" int main( int argc, char** argv ) { IplImage* src; /* the first command line parameter must be image file name */ if( argc==2 && (src = cvLoadImage(argv[1], -1))!=0) {    IplImage* dst = cvCloneImage( src );    int delta = 1;    int angle = 0;         int opt = 1;   // 1: 旋轉加縮放                        // 0: 僅僅旋轉         double factor;         cvNamedWindow( "src", 1 );    cvShowImage( "src", src );

   for(;;)    {     float m[6];             // Matrix m looks like:             //             // [ m0 m1 m2 ] ===> [ A11 A12   b1 ]             // [ m3 m4 m5 ]       [ A21 A22   b2 ]             //     CvMat M = cvMat( 2, 3, CV_32F, m );     int w = src->width;     int h = src->height;     if(opt) // 旋轉加縮放                 factor = (cos(angle*CV_PI/180.) + 1.05)*2;             else // 僅僅旋轉                 factor = 1;     m[0] = (float)(factor*cos(-angle*2*CV_PI/180.));     m[1] = (float)(factor*sin(-angle*2*CV_PI/180.));     m[3] = -m[1];     m[4] = m[0];     // 將旋轉中心移至影象中間             m[2] = w*0.5f;     m[5] = h*0.5f;             // dst(x,y) = A * src(x,y) + b     cvGetQuadrangleSubPix( src, dst, &M);//提取象素四邊形,使用子象素精度     cvNamedWindow( "dst", 1 );     cvShowImage( "dst", dst );     if( cvWaitKey(5) == 27 )      break;     angle =(int) (angle + delta) % 360;    } // for-loop } return 0; }

原始圖:

效果圖:(正變換)

反變換:

正反變換隻是函式中一個引數的不同,具體看你所需要的應用。

cvLogPolar函式可以用來模擬人類的中央視覺(foveal vision),並可以用於物體跟蹤方面的尺度及旋轉不變模板的快速匹配。

原始碼:

#include <cv.h> #include <highgui.h>

int main(int argc, char** argv) {     IplImage* src;

    if( argc == 2 && (src=cvLoadImage(argv[1],1)) != 0 )     {         IplImage* dst = cvCreateImage( cvSize(256,256), 8, 3 );         IplImage* src2 = cvCreateImage( cvGetSize(src), 8, 3 );         cvLogPolar( src, dst, cvPoint2D32f(src->width/2,src->height/2), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS );         cvLogPolar( dst, src2, cvPoint2D32f(src->width/2,src->height/2), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS+CV_WARP_INVERSE_MAP );         cvNamedWindow( "log-polar", 1 );         cvShowImage( "log-polar", dst );         cvNamedWindow( "inverse log-polar", 1 );         cvShowImage( "inverse log-polar", src2 );         cvWaitKey();     }     return 0; }

效果圖:(什麼東東長這麼醜啊,汗)

#include <cv.h> #include <highgui.h> #include <stdlib.h> #include <stdio.h>

IplImage* src = 0; IplImage* dst = 0;

IplConvKernel* element = 0; int element_shape = CV_SHAPE_RECT;

//the address of variable which receives trackbar position update int max_iters = 10; int open_close_pos = 0; int erode_dilate_pos = 0;

// callback function for open/close trackbar void OpenClose(int pos)   {     int n = open_close_pos - max_iters;     int an = n > 0 ? n : -n;     element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, element_shape, 0 );     if( n < 0 )     {         cvErode(src,dst,element,1);         cvDilate(dst,dst,element,1);     }     else     {         cvDilate(src,dst,element,1);         cvErode(dst,dst,element,1);     }     cvReleaseStructuringElement(&element);     cvShowImage("Open/Close",dst); }  

// callback function for erode/dilate trackbar void ErodeDilate(int pos)   {     int n = erode_dilate_pos - max_iters;     int an = n > 0 ? n : -n;     element = cvCreateStructuringElementEx( an*2+1, an*2+1, an, an, element_shape, 0 );     if( n < 0 )     {         cvErode(src,dst,element,1);     }     else     {         cvDilate(src,dst,element,1);     }     cvReleaseStructuringElement(&element);     cvShowImage("Erode/Dilate",dst); }  

int main( int argc, char** argv ) {     char* filename = argc == 2 ? argv[1] : (char*)"baboon.jpg";     if( (src = cvLoadImage(filename,1)) == 0 )         return -1;

    printf( "Hot keys: \n"         "\tESC - quit the program\n"         "\tr - use rectangle structuring element\n"         "\te - use elliptic structuring element\n"         "\tc - use cross-shaped structuring element\n"         "\tENTER - loop through all the options\n" );

    dst = cvCloneImage(src);

    //create windows for output images     cvNamedWindow("Open/Close",1);     cvNamedWindow("Erode/Dilate",1);

    open_close_pos = erode_dilate_pos = max_iters;     cvCreateTrackbar("iterations", "Open/Close",&open_close_pos,max_iters*2+1,OpenClose);     cvCreateTrackbar("iterations", "Erode/Dilate",&erode_dilate_pos,max_iters*2+1,ErodeDilate);

    for(;;)     {         int c;                 OpenClose(open_close_pos);         ErodeDilate(erode_dilate_pos);         c = cvWaitKey(0);

        if( (char)c == 27 )             break;         if( (char)c == 'e' )             element_shape = CV_SHAPE_ELLIPSE;         else if( (char)c == 'r' )             element_shape = CV_SHAPE_RECT;         else if( (char)c == 'c' )             element_shape = CV_SHAPE_CROSS;         else if( (char)c == '\n' )             element_shape = (element_shape + 1) % 3;     }

    //release images     cvReleaseImage(&src);     cvReleaseImage(&dst);

    //destroy windows     cvDestroyWindow("Open/Close");     cvDestroyWindow("Erode/Dilate");

    return 0; }

函式cvSmooth實現各種方法的圖形平滑。

一般來說,影象平滑主要是為了消除噪聲。影象的常見噪聲主要有加性噪聲、乘性噪聲和量化噪聲等。由於影象的能量主要集在低頻部分,而噪聲所在頻段主要在高頻段,因此通常都是採用低通濾波的方法消除噪聲。

函式cvFilter2D對影象做卷積運算。

對影象進行線性濾波,支援替換方式操作。當核運算部份超出輸入影象時,邊界外面的畫素值等於離它最近的影象畫素值。

效果圖:

原始碼:

// Filtering for Image with variaty filtering kernel // // CV_PREWITT_3x3_V A gradient filter (vertical Prewitt operator). //         -1 0 1 //         -1 0 1 //         -1 0 1 // CV_PREWITT_3x3_H A gradient filter (horizontal Prewitt operator). //          1 1 1 //          0 0 0 //         -1 -1 -1 // CV_SOBEL_3x3_V A gradient filter (vertical Sobel operator). //         -1 0 1 //         -2 0 2 //         -1 0 1 // CV_SOBEL_3x3_H A gradient filter (horizontal Sobel operator). //          1 2 1 //          0 0 0 //         -1 -2 -1 // CV_LAPLACIAN_3x3 A 3x3 Laplacian highpass filter. //         -1 -1 -1 //         -1 8 -1 //         -1 -1 -1 // CV_LAPLACIAN_3x3 A 3x3 Laplacian highpass filter (another kernel) // This kernel is similar with function: cvLaplace with aperture_size=1 //          0 1 0 //          1 -4 1 //          0 1 0      注:直接用cvFilter2D得到的結果與用cvLaplace得到的結果 //                           略有不同 // CV_LAPLACIAN_5x5 A 5x5 Laplacian highpass filter. //         -1 -3 -4 -3 -1 //         -3 0 6 0 -3 //         -4 6 20 6 -4 //         -3 0 6 0 -3 //         -1 -3 -4 -3 -1 // CV_GAUSSIAN_3x3 A 3x3 Gaussian lowpass filter. // This filter uses the kernel A/16,where //         1 2 1 //     A = 2 4 2 //         1 2 1 // These filter coefficients correspond to a 2-dimensional Gaussian // distribution with standard deviation 0.85. // // CV_GAUSSIAN_5x5 A 5x5 Gaussian lowpass filter. // This filter uses the kernel A/571,where //         2 7 12 7 2 //         7 31 52 31 7 //    A = 12 52 127 52 12 //         7 31 52 31 7 //         2 7 12 7 2

#include <cv.h> #include <highgui.h> #include <stdio.h>

int main( int argc, char** argv ) { IplImage *src = 0, *dst = 0, *dst2 = 0;     /*float k[9] = { 0, 1, 0,                    1,-4, 1,                    0, 1, 0}; */     float k[9] = { 1.f/16, 2.f/16, 1.f/16,                    2.f/16, 4.f/16, 2.f/16,                    1.f/16, 2.f/16, 1.f/16};   // 這裡高斯核濾波器歸一化     CvMat Km;     //cvInitMatHeader( &Km, 3, 3, CV_32FC1, k, CV_AUTOSTEP );     Km = cvMat( 3, 3, CV_32F, k );

    // 0: force to gray image src = cvLoadImage("lena.jpg", 0);     dst = cvCloneImage( src );

    cvNamedWindow("src", 0);     cvShowImage("src",src);         cvNamedWindow("filtering", 0);     cvFilter2D( src, dst, &Km, cvPoint(-1,-1));     cvShowImage("filtering",dst);     cvWaitKey(0);

    cvReleaseImage( &src );     cvReleaseImage( &dst );     return 0; }

效果圖:

原始碼:

#include "cv.h" #include "highgui.h" #include <stdio.h> #include <stdlib.h>

IplImage* color_img0; IplImage* mask; IplImage* color_img; IplImage* gray_img0 = NULL; IplImage* gray_img = NULL; int ffill_case = 1; int lo_diff = 20, up_diff = 20; int connectivity = 4; int is_color = 1; int is_mask = 0; int new_mask_val = 255;

void on_mouse( int event, int x, int y, int flags, void* param ) {     if( !color_img )         return;

    switch( event )     {     case CV_EVENT_LBUTTONDOWN:         {             CvPoint seed = cvPoint(x,y);             int lo = ffill_case == 0 ? 0 : lo_diff;             int up = ffill_case == 0 ? 0 : up_diff;             int flags = connectivity + (new_mask_val << 8) +                         (ffill_case == 1 ? CV_FLOODFILL_FIXED_RANGE : 0);             int b = rand() & 255, g = rand() & 255, r = rand() & 255;             CvConnectedComp comp;

            if( is_mask )                 cvThreshold( mask, mask, 1, 128, CV_THRESH_BINARY );                         if( is_color )             {                 CvScalar color = CV_RGB( r, g, b );                 cvFloodFill( color_img, seed, color, CV_RGB( lo, lo, lo ),                              CV_RGB( up, up, up ), &comp, flags, is_mask ? mask : NULL );                 cvShowImage( "image", color_img );             }             else             {                 CvScalar brightness = cvRealScalar((r*2 + g*7 + b + 5)/10);                 cvFloodFill( gray_img, seed, brightness, cvRealScalar(lo),                              cvRealScalar(up), &comp, flags, is_mask ? mask : NULL );                 cvShowImage( "image", gray_img );             }

            printf("%g pixels were repainted\n", comp.area );

            if( is_mask )                 cvShowImage( "mask", mask );         }         break;     } }

int main( int argc, char** argv ) {     char* filename = argc >= 2 ? argv[1] : (char*)"fruits.jpg";

    if( (color_img0 = cvLoadImage(filename,1)) == 0 )         return 0;

    printf( "Hot keys: \n"             "\tESC - quit the program\n"             "\tc - switch color/grayscale mode\n"             "\tm - switch mask mode\n"             "\tr - restore the original image\n"             "\ts - use null-range floodfill\n"             "\tf - use gradient floodfill with fixed(absolute) range\n"             "\tg - use gradient floodfill with floating(relative) range\n"             "\t4 - use 4-connectivity mode\n"             "\t8 - use 8-connectivity mode\n" );             color_img = cvCloneImage( color_img0 );     gray_img0 = cvCreateImage( cvSize(color_img->width, color_img->height), 8, 1 );     cvCvtColor( color_img, gray_img0, CV_BGR2GRAY );     gray_img = cvCloneImage( gray_img0 );     mask = cvCreateImage( cvSize(color_img->width + 2, color_img->height + 2), 8, 1 );

    cvNamedWindow( "image", 0 );     cvCreateTrackbar( "lo_diff", "image", &lo_diff, 255, NULL );     cvCreateTrackbar( "up_diff", "image", &up_diff, 255, NULL );

    cvSetMouseCallback( "image", on_mouse, 0 );

    for(;;)     {         int c;                 if( is_color )             cvShowImage( "image", color_img );         else             cvShowImage( "image", gray_img );

        c = cvWaitKey(0);         switch( (char) c )         {         case '\x1b':             printf("Exiting ...\n");             goto exit_main;         case 'c':             if( is_color )             {                 printf("Grayscale mode is set\n");                 cvCvtColor( color_img, gray_img, CV_BGR2GRAY );                 is_color = 0;             }             else             {                 printf("Color mode is set\n");                 cvCopy( color_img0, color_img, NULL );                 cvZero( mask );                 is_color = 1;             }             break;         case 'm':             if( is_mask )             {                 cvDestroyWindow( "mask" );                 is_mask = 0;             }             else             {                 cvNamedWindow( "mask", 0 );                 cvZero( mask );                 cvShowImage( "mask", mask );                 is_mask = 1;             }             break;         case 'r':             printf("Original image is restored\n");             cvCopy( color_img0, color_img, NULL );             cvCopy( gray_img0, gray_img, NULL );             cvZero( mask );             break;         case 's':             printf("Simple floodfill mode is set\n");             ffill_case = 0;             break;         case 'f':             printf("Fixed Range floodfill mode is set\n");             ffill_case = 1;             break;         case 'g':             printf("Gradient (floating range) floodfill mode is set\n");             ffill_case = 2;             break;         case '4':             printf("4-connectivity mode is set\n");             connectivity = 4;             break;         case '8':             printf("8-connectivity mode is set\n");             connectivity = 8;             break;         }     }

exit_main:

    cvDestroyWindow( "test" );     cvReleaseImage( &gray_img );     cvReleaseImage( &gray_img0 );     cvReleaseImage( &color_img );     cvReleaseImage( &color_img0 );     cvReleaseImage( &mask );

    return 1; }

效果視訊我上傳了,瀏覽網址(個人感覺很牛,有點像生化危機裡的一個場景):

如果上面的卡,可以連這個,就是有點發散圖形:

也不說什麼了,直接給程式碼吧(有一句話想說,實際上如果你是拿來做實際專案的,可能並不要學習裡面的演算法,直接利用裡面的模板,也就是外接的呼叫函式就可以了):

#include "cv.h" #include "highgui.h" #include <time.h> #include <math.h> #include <ctype.h> #include <stdio.h> #include <string.h>

// various tracking parameters (in seconds) const double MHI_DURATION = 0.5; const double MAX_TIME_DELTA = 0.5; const double MIN_TIME_DELTA = 0.05; const int N = 3;

// const int CONTOUR_MAX_AERA = 16;

// ring image buffer IplImage **buf = 0; int last = 0;

// temporary images IplImage *mhi = 0; // MHI: motion history image

CvFilter filter = CV_GAUSSIAN_5x5; CvConnectedComp *cur_comp, min_comp; CvConnectedComp comp; CvMemStorage *storage; CvPoint pt[4];

// 引數: // img – 輸入視訊幀 // dst – 檢測結果 void update_mhi( IplImage* img, IplImage* dst, int diff_threshold ) {     double timestamp = clock()/100.; // get current time in seconds     CvSize size = cvSize(img->width,img->height); // get current frame size     int i, j, idx1, idx2;     IplImage* silh;     uchar val;     float temp;     IplImage* pyr = cvCreateImage( cvSize((size.width & -2)/2, (size.height & -2)/2), 8, 1 );     CvMemStorage *stor;     CvSeq *cont, *result, *squares;     CvSeqReader reader;

    if( !mhi || mhi->width != size.width || mhi->height != size.height )     {         if( buf == 0 )         {             buf = (IplImage**)malloc(N*sizeof(buf[0]));             memset( buf, 0, N*sizeof(buf[0]));         }                 for( i = 0; i < N; i++ )         {             cvReleaseImage( &buf[i] );             buf[i] = cvCreateImage( size, IPL_DEPTH_8U, 1 );             cvZero( buf[i] );         }         cvReleaseImage( &mhi );         mhi = cvCreateImage( size, IPL_DEPTH_32F, 1 );         cvZero( mhi ); // clear MHI at the beginning     } // end of if(mhi)

    cvCvtColor( img, buf[last], CV_BGR2GRAY ); // convert frame to grayscale

    idx1 = last;     idx2 = (last + 1) % N; // index of (last - (N-1))th frame     last = idx2;

    // 做幀差     silh = buf[idx2];     cvAbsDiff( buf[idx1], buf[idx2], silh ); // get difference between frames         // 對差影象做二值化     cvThreshold( silh, silh, 30, 255, CV_THRESH_BINARY ); // and threshold it         cvUpdateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI     cvCvtScale( mhi, dst, 255./MHI_DURATION,       (MHI_DURATION - timestamp)*255./MHI_DURATION );        cvCvtScale( mhi, dst, 255./MHI_DURATION, 0 );            // 中值濾波,消除小的噪聲     cvSmooth( dst, dst, CV_MEDIAN, 3, 0, 0, 0 );         // 向下取樣,去掉噪聲     cvPyrDown( dst, pyr, 7 );     cvDilate( pyr, pyr, 0, 1 ); // 做膨脹操作,消除目標的不連續空洞     cvPyrUp( pyr, dst, 7 );     //     // 下面的程式段用來找到輪廓     //     // Create dynamic structure and sequence.     stor = cvCreateMemStorage(0);     cont = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint) , stor);         // 找到所有輪廓     cvFindContours( dst, stor, &cont, sizeof(CvContour),                     CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0)); /*     for(;cont;cont = cont->h_next)     {           // Number point must be more than or equal to 6 (for cvFitEllipse_32f).                if( cont->total < 6 )             continue;

        // Draw current contour.         cvDrawContours(img,cont,CV_RGB(255,0,0),CV_RGB(255,0,0),0,1, 8, cvPoint(0,0));     } // end of for-loop: "cont" */     // 直接使用CONTOUR中的矩形來畫輪廓     for(;cont;cont = cont->h_next)     {               CvRect r = ((CvContour*)cont)->rect;               if(r.height * r.width > CONTOUR_MAX_AERA) // 面積小的方形拋棄掉               {                   cvRectangle( img, cvPoint(r.x,r.y),                           cvPoint(r.x + r.width, r.y + r.height),                           CV_RGB(255,0,0), 1, CV_AA,0);               }     }     // free memory     cvReleaseMemStorage(&stor);     cvReleaseImage( &pyr ); }

int main(int argc, char** argv) {     IplImage* motion = 0;     CvCapture* capture = 0; //視訊獲取結構         if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) //原型:extern int isdigit(char c); //用法:#include <ctype.h>   功能:判斷字元c是否為數字    說明:當c為數字0-9時,返回非零值,否則返回零。         capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 );     else if( argc == 2 )         capture = cvCaptureFromAVI( argv[1] );     if( capture )     {         cvNamedWindow( "Motion", 1 );         for(;;)         {             IplImage* image;             if( !cvGrabFrame( capture )) //從攝像頭或者視訊檔案中抓取幀                 break;             image = cvRetrieveFrame( capture ); //取回由函式cvGrabFrame抓取的影象,返回由函式cvGrabFrame 抓取的影象的指標             if( image )             {                 if( !motion )                 {                     motion = cvCreateImage( cvSize(image->width,image->height), 8, 1 );                     cvZero( motion );                     motion->origin = image->origin; ///* 0 - 頂—左結構, 1 - 底—左結構 (Windows bitmaps 風格) */                 }             }

            update_mhi( image, motion, 60 );             cvShowImage( "Motion", image );

            if( cvWaitKey(10) >= 0 )                 break;         }         cvReleaseCapture( &capture );         cvDestroyWindow( "Motion" );     }     return 0; }

影象分割指的是將數字影象細分為多個影象子區域的過程,在OpenCv中實現了三種跟影象分割相關的演算法,它們分別是:分水嶺分割演算法、金字塔分割演算法以及均值漂移分割演算法。

分水嶺分割演算法     分水嶺分割演算法需要您或者先前演算法提供標記,該標記用於指定哪些大致區域是目標,哪些大致區域是背景等等;分水嶺分割演算法的分割效果嚴重依賴於提供的標記。OpenCv中的函式cvWatershed實現了該演算法

金字塔分割演算法     金字塔分割演算法由cvPrySegmentation所實現,該函式的使用很簡單;需要注意的是影象的尺寸以及金字塔的層數,影象的寬度和高度必須能被2整除,能夠被2整除的次數決定了金字塔的最大層數

均值漂移分割演算法     均值漂移分割演算法由cvPryMeanShiftFiltering所實現,均值漂移分割的金字塔層數只能介於[1,7]之間

友情連結一下,個人感覺比較好的這方面部落格:

效果圖:

#include "cv.h" #include "highgui.h" #include <math.h>

IplImage* image[2] = { 0, 0 }, *image0 = 0, *image1 = 0; CvSize size;

int w0, h0,i; int threshold1, threshold2; int l,level = 4; int sthreshold1, sthreshold2; int l_comp; int block_size = 1000; float parameter; double threshold; double rezult, min_rezult; CvFilter filter = CV_GAUSSIAN_5x5; CvConnectedComp *cur_comp, min_comp; CvSeq *comp; CvMemStorage *storage;

CvPoint pt1, pt2;

void ON_SEGMENT(int a) {       cvPyrSegmentation(image0, image1, storage, &comp,                       level, threshold1+1, threshold2+1);

    /*l_comp = comp->total;

    i = 0;     min_comp.value = cvScalarAll(0);     while(i<l_comp)     {         cur_comp = (CvConnectedComp*)cvGetSeqElem ( comp, i );         if(fabs(255- min_comp.value.val[0])>            fabs(255- cur_comp->value.val[0]) &&            fabs(min_comp.value.val[1])>            fabs(cur_comp->value.val[1]) &&            fabs(min_comp.value.val[2])>            fabs(cur_comp->value.val[2]) )            min_comp = *cur_comp;         i++;     }*/     cvShowImage("Segmentation", image1); }

int main( int argc, char** argv ) {     char* filename = argc == 2 ? argv[1] : (char*)"fruits.jpg";         if( (image[0] = cvLoadImage( filename, 1)) == 0 )         return -1;     cvNamedWindow("Source", 0);     cvShowImage("Source", image[0]);

    cvNamedWindow("Segmentation", 0);

    storage = cvCreateMemStorage ( block_size );

    image[0]->width &= -(1<<level);     image[0]->height &= -(1<<level);

    image0 = cvCloneImage( image[0] );     image1 = cvCloneImage( image[0] );     // 對彩色影象進行分割     l = 1;     threshold1 =255;     threshold2 =30;

    ON_SEGMENT(1);

sthreshold1 = cvCreateTrackbar("Threshold1", "Segmentation", &threshold1, 255, ON_SEGMENT); sthreshold2 = cvCreateTrackbar("Threshold2", "Segmentation", &threshold2, 255, ON_SEGMENT);

    cvShowImage("Segmentation", image1);     cvWaitKey(0);

    cvDestroyWindow("Segmentation");     cvDestroyWindow("Source");

    cvReleaseMemStorage(&storage );

    cvReleaseImage(&image[0]);     cvReleaseImage(&image0);     cvReleaseImage(&image1);

    return 0; }

鬱悶,以前用過MatLab,很長時間沒用了,都不知道怎麼使了,據說做這個效果很不錯。

效果圖:

原始碼:

#include "cv.h" #include "highgui.h" /* src and dst are grayscale, 8-bit images; Default input value:            [low, high] = [0,1]; X-Direction            [bottom, top] = [0,1]; Y-Direction            gamma ; if adjust successfully, return 0, otherwise, return non-zero. */ int ImageAdjust(IplImage* src, IplImage* dst,     double low, double high,   // X方向:low and high are the intensities of src     double bottom, double top, // Y方向:mapped to bottom and top of dst     double gamma ) { if( low<0 && low>1 && high <0 && high>1&& bottom<0 && bottom>1 && top<0 && top>1 && low>high)         return -1;     double low2 = low*255;     double high2 = high*255;     double bottom2 = bottom*255;     double top2 = top*255;     double err_in = high2 - low2;     double err_out = top2 - bottom2;

    int x,y;     double val;

    // intensity transform     for( y = 0; y < src->height; y++)     {         for (x = 0; x < src->width; x++)         {             val = ((uchar*)(src->imageData + src->widthStep*y))[x];             val = pow((val - low2)/err_in, gamma) * err_out + bottom2;             if(val>255) val=255; if(val<0) val=0; // Make sure src is in the range [low,high]             ((uchar*)(dst->imageData + dst->widthStep*y))[x] = (uchar) val;         }     }     return 0; }

int main( int argc, char** argv ) {     IplImage *src = 0, *dst = 0;         if( argc != 2 || (src=cvLoadImage(argv[1], 0)) == NULL) // force to gray image         return -1;         cvNamedWindow( "src", 1 );     cvNamedWindow( "result", 1 );         // Image adjust     dst = cvCloneImage(src);     // 輸入引數 [0,0.5] 和 [0.5,1], gamma=1 if( ImageAdjust( src, dst, 0, 0.5, 0.5, 1, 1)!=0) return -1;         cvShowImage( "src", src );     cvShowImage( "result", dst );     cvWaitKey(0);

    cvDestroyWindow("src");     cvDestroyWindow("result");     cvReleaseImage( &src );     cvReleaseImage( &dst );         return 0; }

原始圖:

效果圖:

原始碼:

#inclu