本章開始學習新的內容,如何從圖像中將目標或部分目標分割出來,也希望將感興趣的目標區域分割出來,比如將一個人的臉或手分割出來。背景減除(差分)是最基本的圖像處理操作,處理方法是建立背景模型,然後將背景模型和當前的圖像進行比較,減去這些已知的背景信息,則剩下的目標物大致就是所求的前景目標了,但是該方法受累於一個不常成立的假設:所有像素點都是獨立的。本例程考察圖像中的像素點在一段時間內如何變化,從視頻中讀出一行直線,對這條直線的像素的RGB值進行採樣,收集這些數值並存入三個文件。大致的思路參見代碼註釋。
本視頻30s,68幀畫面,每次採樣11個像素點,總共有3*68*11個數據。
----------------------------------------------------------------------------------------------------
數據結構:CvLineIterator iter; //採樣迭代器
方法:
cvCreateFileCapture
初始化從文件中獲取視頻
CvCapture* cvCreateFileCapture( const char* filename );
filename
視頻文件名。
函數cvCreateFileCapture給指定文件中的視頻流分配和初始化CvCapture結構。
當分配的結構不再使用的時候,它應該使用cvReleaseCapture函數釋放掉。
cvGrabFrame
從攝像頭或者視頻文件中抓取幀
int cvGrabFrame( CvCapture* capture );
capture
視頻獲取結構指針。
函數cvGrabFrame從攝像頭或者文件中抓取幀。被抓取的幀在內部被存儲。這個函數的目的是快速的抓取幀,這一點對同時從幾個攝像頭讀取數據的同步是很重要的。被抓取的幀可能是壓縮的格式(由攝像頭/驅動定義),所以沒有被公開出來。如果要取回獲取的幀,請使用cvRetrieveFrame。
cvRetrieveFrame
取回由函數cvGrabFrame抓取的圖像
IplImage* cvRetrieveFrame( CvCapture* capture );
capture
視頻獲取結構。
函數cvRetrieveFrame返回由函數cvGrabFrame抓取的圖像的指針。返回的圖像不可以被用戶釋放或者修改。
InitLineIterator 初始化直線迭代器
int cvInitLineIterator( const CvArr* image, CvPoint pt1, CvPoint pt2, CvLineIterator* line_iterator, int connectivity=8, int left_to_right=0 ); img 用以獲取直線的圖像。 pt1 線段的第一個端點。 pt2 線段的第二個端點。 line_iterator 指向直線迭代狀態結構體的指針。 connectivity 直線的鄰接方式,4鄰接或者8鄰接。 left_to_right 標誌值,指出掃描直線是從pt1和pt2外面最左邊的點掃描到最右邊的點(left_to_right≠0),還是按照指定的順序,從pt1到pt2(left_to_right=0)。 函數cvInitLineIterator初始化直線迭代器並返回兩個端點間點的數目。兩個端點都必須在圖像內部。在迭代器初始化以後,所有的在連接兩個終點的柵欄線上的點,可以通過訪問CV_NEXT_LINE_POINT點的方式獲得。在線上的這些點使用4-鄰接或者8-鄰接的Bresenham算法計算得到。 |
-----------------------------------------------------------------------------------------
/*code*/
程序註釋表達了思路。
- #include <cv.h>
- #include <highgui.h>
- #include <stdio.h>
- int main( int argc, char** argv )
- {
- if( argc != 2 )
- return -1;
- cvNamedWindow( "Example", CV_WINDOW_AUTOSIZE );
- CvCapture* capture = cvCreateFileCapture( argv[1] ); //加載視頻
- if( !capture )
- printf( "Couldn't open %s\n", argv[1] );
- CvPoint pt1 = cvPoint( 10, 10 );
- CvPoint pt2 = cvPoint( 10, 20 ); //直線兩個頂點,讀取這兩個端點連成直線的像素點,總共11個像素點
- int max_buffer;
- IplImage* rawImage;
- int r[10000], g[10000], b[10000]; //存儲r,g,b三維的像素值
- FILE* fptrb = fopen( "blines.csv","w" ); //創建文件存儲數據
- FILE* fptrg = fopen( "glines.csv", "w" ); //存儲每個通道的像素值
- FILE* fptrr = fopen( "rlines.csv", "w" ); //存儲爲csv文件
- CvLineIterator iter; //採樣迭代器
- int sign = 0;
- for( ;; )
- {
- if( !cvGrabFrame( capture ) ) //如果沒捕捉到幀,退出,視頻總共有68幀,30秒的畫面
- break;
- rawImage = cvRetrieveFrame( capture ); //取回由函數cvGrabFrame抓取的圖像
- max_buffer = cvInitLineIterator( rawImage, pt1, pt2, &iter, 8, 0); //初始化直線迭代器,返回直線上兩端像素點個數,總共11個
- cvShowImage( "Example", rawImage ); //顯示每一幀,連續顯示每一幀就是視頻的的原理
- int c = cvWaitKey(0);
- for( int j = 0; j < max_buffer; ++j ) //max_buffer = 11
- {
- fprintf( fptrb, "%d,", iter.ptr[0] ); //寫藍值
- fprintf( fptrg, "%d,", iter.ptr[1] );
- fprintf( fptrr, "%d,", iter.ptr[2] );
- iter.ptr[2] = 255; //將直線標記爲紅色
- CV_NEXT_LINE_POINT( iter ); //移動指針,指向下一個pixel
- }
- fprintf( fptrb, "\n" );
- fprintf( fptrg, "\n" );
- fprintf( fptrr, "\n" );
- sign++;
- printf("\n\n%d", sign);
- }
- fclose( fptrb );
- fclose( fptrg );
- fclose( fptrr );
- cvReleaseCapture( &capture );
- cvDestroyWindow( "Example" );
- return 0;
- }
-----------------------------------------------------------------------------------------
/*result*/
capture frame 38
capture frame 60
pixel files