変形と置換
■ 変形
OpenCVのCXCOREリファレンス マニュアルのTransforms and Permutationsに分類される関数のうち,Transformsには,画像や配列の形状や構造を変えるための関数が用意されている. 特に,データのコピーなしにヘッダ情報を書き換える事でその形状を変化させている.サンプル
画像形状の変形 cvReshape
データをコピーせずに,3チャンネル画像を各チャンネルデータを展開した1チャンネル画像に変形する
サンプルコード
#include <cv.h> #include <highgui.h> #include <stdio.h> int main (int argc, char **argv) { IplImage *src_img = 0; IplImage img_hdr, *dst_img; CvMat mat_hdr; // (1)画像を読み込む if (argc >= 2) src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR); if (src_img == 0) return -1; // (2)画像形状の変更を行う cvReshape (src_img, &mat_hdr, 1, 0); dst_img = cvGetImage (&mat_hdr, &img_hdr); printf ("src_img size:[ %d, %d ] data-pointer:[%p]\n", src_img->width, src_img->height, src_img->imageData); printf ("mat_hdr size:[ %d, %d ] data-pointer:[%p]\n", mat_hdr.width, mat_hdr.height, mat_hdr.data.ptr); // (3)結果を表示する cvNamedWindow ("src", CV_WINDOW_AUTOSIZE); cvNamedWindow ("dst", CV_WINDOW_AUTOSIZE); cvShowImage ("src", src_img); cvShowImage ("dst", dst_img); cvWaitKey (0); cvDestroyWindow ("src"); cvDestroyWindow ("dst"); cvReleaseImage (&src_img); return 1; }
// (1)画像を読み込む
コマンド引数で指定されたファイル名の画像(入力画像)をオープンし,関数
cvLoadImage()で読み込む.2番目の引数にCV_LOAD_IMAGE_COLORを指定することで,
デプス8ビット,3チャンネルのカラー画像として読み込む.
// (2)画像形状の変更を行う
関数cvReshape()の3番目の引数で,チャンネル数を1に設定.4番根の引数に0を指定
することで,配列の行数(画像の高さに相当)を変えずに配列のサイズを変える.
これは,配列の列数(画像の幅)を3倍する事を意味している.
cvReshape()はCvMat型のヘッダを返すため,関数cvGetImage()で,IplImage構造体のヘッダ
に変換している.
この後のprintf文で出力される情報を確認すると,データへのポインタは同じである事がわかる.
// (3)結果を表示する
形状を変換した画像を表示し,何かキーが押されるまで待つ.
実行結果例
■ 置換
OpenCVのCXCOREリファレンス マニュアルのTransforms and Permutationsに分類される関数のうち, Permutationsには,データの置換による配列(画像)のマッピングや反転などを行なう基本的な関数が 用意されている.サンプル
タイリング cvRepeat
画像のタイリングを行なう
サンプルコード
#include <cv.h> #include <highgui.h> #include <stdio.h> int main (int argc, char **argv) { IplImage *src_img = 0; IplImage *dst_img; // (1)画像を読み込む if (argc >= 2) src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR); if (src_img == 0) return -1; // (2)出力画像領域を作成し,入力画像をタイリングする dst_img = cvCreateImage (cvSize (384, 512), IPL_DEPTH_8U, 3); cvRepeat (src_img, dst_img); // (3)結果を表示する cvNamedWindow ("src", CV_WINDOW_AUTOSIZE); cvNamedWindow ("dst", CV_WINDOW_AUTOSIZE); cvShowImage ("src", src_img); cvShowImage ("dst", dst_img); cvWaitKey (0); cvDestroyWindow ("src"); cvDestroyWindow ("dst"); cvReleaseImage (&src_img); cvReleaseImage (&dst_img); return 1; }
// (1)画像を読み込む
コマンド引数で指定されたファイル名の画像(入力画像)をオープンし,関数
cvLoadImage()で読み込む.2番目の引数にCV_LOAD_IMAGE_COLORを指定することで,
デプス8ビット,3チャンネルのカラー画像として読み込む.
// (2)出力画像領域を作成し,入力画像をタイリングする
関数cvCreateImage()によって,幅384,高さ512の画像領域を生成する.
生成した画像に対して,関数cvRepeat()を用いて入力画像をタイリングする.
// (3)結果を表示する
処理された画像を実際に表示し,何かキーが押されるまで待つ.
実行結果例
入力画像(256x192)が出力画像(384x512)より小さい場合
入力画像(512x384)が出力画像(384x512)より幅が大きい場合
画像の反転 cvFlip(1)
画像の垂直・水平・両軸反転を行う
サンプルコード
#include <cv.h> #include <highgui.h> int main (int argc, char **argv) { IplImage *src_img = 0; IplImage *dst_img_1, *dst_img_2, *dst_img_3; // (1)画像を読み込み,同じサイズの出力画像を用意する if (argc >= 2) src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR); if (src_img == 0) return -1; dst_img_1 = cvCloneImage (src_img); dst_img_2 = cvCloneImage (src_img); dst_img_3 = cvCloneImage (src_img); // (2)画像の水平軸反転・垂直軸反転・両軸反転を行う cvFlip (src_img, dst_img_1, 0); cvFlip (src_img, dst_img_2, 1); cvFlip (src_img, dst_img_3, -1); // (3)結果を表示する cvNamedWindow ("src", CV_WINDOW_AUTOSIZE); cvNamedWindow ("dst_1", CV_WINDOW_AUTOSIZE); cvNamedWindow ("dst_2", CV_WINDOW_AUTOSIZE); cvNamedWindow ("dst_3", CV_WINDOW_AUTOSIZE); cvShowImage ("src", src_img); cvShowImage ("dst_1", dst_img_1); cvShowImage ("dst_2", dst_img_2); cvShowImage ("dst_3", dst_img_3); cvWaitKey (0); cvDestroyWindow ("src"); cvDestroyWindow ("dst_1"); cvDestroyWindow ("dst_2"); cvDestroyWindow ("dst_3"); cvReleaseImage (&src_img); cvReleaseImage (&dst_img_1); cvReleaseImage (&dst_img_2); cvReleaseImage (&dst_img_3); return 1; }
// (1)画像を読み込み,同じサイズの出力画像を用意する
コマンド引数で指定されたファイル名の画像(入力画像)をオープンし,関数cvLoadImage()で読み込む.
また,反転後の画像を保存するために3つの画像領域を生成する.
// (2)画像の水平軸反転・垂直軸反転・両軸反転を行う
関数cvFlip()によって,画像の反転を行なう.
3番目の引数に0を指定し水平軸反転を,1(>0)を指定し垂直軸反転を,
-1(<0)を指定し両軸反転を行う.
// (3)結果を表示する
処理された画像を実際に表示し,何かキーが押されるまで待つ.
実行結果例
入力画像 | 水平軸反転 | 垂直軸反転 | 両軸反転 |
ROIを利用した画像の部分反転 cvFlip(2)
ROIを利用して画像の一部分に対して垂直・水平・両軸反転を行う
サンプルコード
#include <cv.h> #include <highgui.h> int main (int argc, char **argv) { int w, h; IplImage *src_img = 0; IplImage *dst_img; // (1)画像を読み込み,入力画像をコピーした出力画像を用意する if (argc >= 2) src_img = cvLoadImage (argv[1], CV_LOAD_IMAGE_COLOR); if (src_img == 0) return -1; dst_img = cvCloneImage (src_img); // (2)出力画像にROIをセットし各部に対して水平軸反転・垂直軸反転・両軸反転をインプレースモードで行う w = dst_img->width / 2; h = dst_img->height / 2; cvSetImageROI (dst_img, cvRect (w, 0, w, h)); cvFlip (dst_img, NULL, 0); cvSetImageROI (dst_img, cvRect (0, h, w, h)); cvFlip (dst_img, NULL, 1); cvSetImageROI (dst_img, cvRect (w, h, w, h)); cvFlip (dst_img, NULL, -1); cvResetImageROI (dst_img); // (3)結果を表示する cvLine (src_img, cvPoint (0, h), cvPoint (src_img->width - 1, h), CV_RGB (255, 0, 255), 2, 8, 0); cvLine (src_img, cvPoint (w, 0), cvPoint (w, src_img->height - 1), CV_RGB (255, 0, 255), 2, 8, 0); cvNamedWindow ("src", CV_WINDOW_AUTOSIZE); cvNamedWindow ("dst", CV_WINDOW_AUTOSIZE); cvShowImage ("src", src_img); cvShowImage ("dst", dst_img); cvWaitKey (0); return 1; }
// (1)(1)画像を読み込み,入力画像をコピーした出力画像を用意する
コマンド引数で指定されたファイル名の画像(入力画像)をオープンし,関数cvLoadImage()で読み込む.
また,処理用の画像として入力画像のコピーを生成する.
// (2)出力画像にROIをセットし各部に対して水平軸反転・垂直軸反転・両軸反転をインプレースモードで行う
画像を4分割し,最初に右上の領域をROIとしてセットする.
続いて関数cvFlip()の2番目の引数にNULLを指定し,3番目の引数に0を指定することで,
セットしたROI領域に対してインプレースモードで部分的な水平軸反転を行う.
続いて同様の方法でに,左下領域,右下領域に対してそれぞれ垂直軸反転(第3引数に1を指定),
両軸反転(第3引数に-1を指定)を行う.
最後にcvResetImageROI()で,ROIを解放する.
// (3)結果を表示する
入力画像の4分割の領域を表示するために,入力画像src_img上にcvLine()で水平・垂直線分を描画する.
処理された画像を実際に表示し,何かキーが押されるまで待つ.
実行結果例
入力画像(分割領域を表示)と部分反転を行なった出力画像