cvSplit 使用例
opencv.jp での cvSplit
opencv.jp - OpenCV-1.0:CXCORE 変形と置換(Transforms and Permutations)リファレンス マニュアル -Split
マルチチャンネルの配列を,複数のシングルチャンネルの配列に分割する.または,配列から一つのチャンネルを取り出す.
void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1, CvArr* dst2, CvArr* dst3 ); #define cvCvtPixToPlane cvSplit関数cvSplitは,マルチチャンネルの配列をシングルチャンネルの配列に分割する.この操作には二つのモードがある.入力配列がNチャンネルの場合,先頭からN番目までの出力チャンネルが NULL でなければ,それらはすべて入力配列から取り出される.そうでなく,N個の出力チャンネルのうち一つだけが NULL でない場合は,この特定のチャンネルのみを抽出する.このいずれでもない場合はエラーとなる. N番目以降の出力チャンネルは常に NULL でなくてはならない. IplImageでは,画像から一つのシングルチャンネルを抽出するために,COIを伴うcvCopyも利用される.src 入力配列. dst0...dst3 出力チャンネル.
使用例概要
動画を読み込み,静止画を出力する.
入力動画 | const char *IN_AVI_FILE[] | main 関数で数値を入れ,ファイルを指定する |
---|---|---|
出力フォルダ | const char *OUT_STILL_DIR[] | OpenCV の仕様に従い BGR 順とする |
出力画像形式 | const char *OUT_STILL_FILENAME_TAIL | BMP や JPEG にしたいときに変更する |
メモ
cvSplit の書き込み先はメモリ確保しておく必要がある.
- 出力フォルダを削除
- 出力フォルダを作成
- 主処理
- 動画から静止画を読み出す
- 静止画を色平面ごとに分割する
- 各色平面をファイル出力する
ソース
/* * 入力: AVI ファイル * 出力: PNG ファイル 色平面ごとに分割して保存する */ #include "cv.h" #include "cxcore.h" #include "highgui.h" #include <stdio.h> #include <stdlib.h> #pragma comment(lib, "cv.lib") #pragma comment(lib, "cxcore.lib") #pragma comment(lib, "highgui.lib") // 入力ファイル const char *IN_AVI_FILE[] = { "c:\\data\\video\\90frame.avi", "c:\\data\\video\\360frame.avi", "c:\\data\\video\\1858frame.avi", }; // 出力フォルダ const char *OUT_STILL_DIR[] = { "c:\\data\\image\\avi2rgbstill\\b\\", "c:\\data\\image\\avi2rgbstill\\g\\", "c:\\data\\image\\avi2rgbstill\\r\\", }; // 出力ファイル名最大長 const int OUT_FILENAME_MAXLEN = 512; // 出力画像拡張子 const char *OUT_STILL_FILENAME_TAIL = ".png"; // 出力フォルダを削除 // // /S 指定されたディレクトリに加えて、そのディレクトリ内のすべての // ディレクトリとファイルを削除します。ディレクトリ ツリーを削除 // するときに使用します。 // // /Q /S を指定してディレクトリ ツリーを削除するときに、確認の // メッセージを表示しません。(QUIET モード) void deleteOutdir() { char system_call[512]; for ( int channel = 0; channel < 3; channel++ ) { sprintf_s(system_call, 512, "rmdir /s /q %s", OUT_STILL_DIR[channel]); system(system_call); } } // 出力フォルダを作成 void makeOutkdir() { char system_call[512]; for ( int channel = 0; channel < 3; channel++ ) { sprintf_s(system_call, 512, "mkdir %s", OUT_STILL_DIR[channel]); system(system_call); } } // BGR 各平面の画像保存 void saveStill( IplImage **img_planes ) { static int img_counter = 0; static char out_still_filename[OUT_FILENAME_MAXLEN]; for ( int channel = 0; channel < 3; channel++ ) { sprintf_s(out_still_filename, OUT_FILENAME_MAXLEN, "%s%d%s", OUT_STILL_DIR[channel], img_counter, OUT_STILL_FILENAME_TAIL); cvSaveImage(out_still_filename, img_planes[channel]); } img_counter++; } // BGR 各平面の画像メモリ確保.解放はプログラム終端で手書きすること void planesInit( CvCapture *capture, IplImage **img_planes) { int width = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH); int height = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT); for ( int channel = 0; channel < 3; channel++ ) { img_planes[channel] = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 1); } } int main(int argc, char **argv) { CvCapture *capture = cvCaptureFromAVI(IN_AVI_FILE[1]); IplImage *img_query; IplImage *img_planes[3] = { NULL, NULL, NULL, }; deleteOutdir(); makeOutkdir(); planesInit(capture, img_planes); while( img_query = cvQueryFrame(capture) ) { cvSplit(img_query, img_planes[0], img_planes[1], img_planes[2], NULL); saveStill(img_planes); } cvReleaseImage(&img_planes[0]); cvReleaseImage(&img_planes[1]); cvReleaseImage(&img_planes[2]); cvReleaseCapture(&capture); return 0; }