今度は、1ピクセルごとにデータをいじりたいと思います。
というわけで今回のお題は色相関。
↓こんなの
横幅360ピクセルの画像を生成して、
1ピクセルごとに青、緑、赤の値を変化させていっています。
関数を使ったものと、ポインタで直接値を変更したものを作ってみました。
//色相関みたいなものを作る #include "cv.h" #include "highgui.h" double g_cvSet2DTime; double g_PointerTime; void SetScalarToPixcel(IplImage* img,int x, int setblue, int setgreen, int setred); void SetScalarToPixcel_PointVer(IplImage* img,int x, int setblue, int setgreen, int setred); int main( int argc, char** argv ) { //表示用のウィンドウを作る cvNamedWindow("Gradation",CV_WINDOW_AUTOSIZE); cvNamedWindow("Gradation2",CV_WINDOW_AUTOSIZE); g_cvSet2DTime=0.0; g_PointerTime=0.0; //空っぽのイメージを作成 IplImage * colorMap=cvCreateImage(cvSize(360,40),IPL_DEPTH_8U,3); //IPL_DEPTH_8U 符号なし8ビット整数 IplImage * colorMapPointer=cvCreateImage(cvSize(360,40),IPL_DEPTH_8U,3); //初期化(真っ黒になる) cvZero(colorMap); cvZero(colorMapPointer); //WikiPediaに色相関を作る方法が載っていたのでそれを参考に作成します。 // 青 緑 赤 // 0°- 60° 0固定 0から255へ 255固定 // 60°-120° 0固定 255固定 255から0へ //120°-180° 0から255へ 255固定 0固定 //180°-240° 255固定 255から0へ 0固定 //240°-300° 255固定 0固定 0から255へ //300°-360° 255から0へ 0固定 255固定 // int modular=0; int addvalue=0; for(int degree=1;degree<=360;degree++) { modular=(degree)%60; if(degree==60) { SetScalarToPixcel(colorMap,degree,0,255,255); SetScalarToPixcel_PointVer(colorMapPointer,degree,0,255,255); } if(degree==120) { SetScalarToPixcel(colorMap,degree,0,255,0); SetScalarToPixcel_PointVer(colorMapPointer,degree,0,255,0); } if(degree==180) { SetScalarToPixcel(colorMap,degree,255,255,0); SetScalarToPixcel_PointVer(colorMapPointer,degree,255,255,0); } if(degree==240) { SetScalarToPixcel(colorMap,degree,255,0,0); SetScalarToPixcel_PointVer(colorMapPointer,degree,255,0,0); } if(degree==300) { SetScalarToPixcel(colorMap,degree,255,0,255); SetScalarToPixcel_PointVer(colorMapPointer,degree,255,0,255); } if(degree==360) { SetScalarToPixcel(colorMap,degree,0,0,255); SetScalarToPixcel_PointVer(colorMapPointer,degree,0,0,255); } if( 0<=degree && degree< 60) { addvalue=modular*4; SetScalarToPixcel(colorMap,degree,0,addvalue,255); SetScalarToPixcel_PointVer(colorMapPointer,degree,0,addvalue,255); } if( 60<degree && degree<120) { addvalue=255-modular*4; SetScalarToPixcel(colorMap,degree,0,255,addvalue); SetScalarToPixcel_PointVer(colorMapPointer,degree,0,255,addvalue); } if(120<degree && degree<180) { addvalue=modular*4; SetScalarToPixcel(colorMap,degree,addvalue,255,0); SetScalarToPixcel_PointVer(colorMapPointer,degree,addvalue,255,0); } if(180<degree && degree<240) { addvalue=255-modular*4; SetScalarToPixcel(colorMap,degree,255,addvalue,0); SetScalarToPixcel_PointVer(colorMapPointer,degree,255,addvalue,0); } if(240<degree && degree<300) { addvalue=modular*4; SetScalarToPixcel(colorMap,degree,255,0,addvalue); SetScalarToPixcel_PointVer(colorMapPointer,degree,255,0,addvalue); } if(300<degree && degree<360) { addvalue=255-modular*4; SetScalarToPixcel(colorMap,degree,addvalue,0,255); SetScalarToPixcel_PointVer(colorMapPointer,degree,addvalue,0,255); } } cvShowImage("Gradation",colorMap); cvShowImage("Gradation2",colorMapPointer); printf( "execution time(cvSet2D) = %g ms\n", g_cvSet2DTime/((double)cvGetTickFrequency()*1000.) ); printf( "execution time(Pointer) = %g ms\n", g_PointerTime/((double)cvGetTickFrequency()*1000.) ); //5秒間表示 cvWaitKey(5000); //リソースの開放 cvReleaseImage(&colorMap); cvReleaseImage(&colorMapPointer); cvDestroyWindow("Gradation"); cvDestroyWindow("Gradation2"); } void SetScalarToPixcel(IplImage* img,int x, int setblue, int setgreen, int setred) { double t = 0; t = (double)cvGetTickCount(); for(int y=0;y<img->height;y++) { //インデックスがheight,widthの順で並んでるので注意 cvSet2D( img, y, x-1, cvScalar(setblue,setgreen,setred) ); } t = (double)cvGetTickCount() - t; g_cvSet2DTime=g_cvSet2DTime+t; } void SetScalarToPixcel_PointVer(IplImage* img,int x, int setblue, int setgreen, int setred) { double t = 0; t = (double)cvGetTickCount(); for(int y=0;y<img->height;y++) { uchar* ptr=(uchar*)(img->imageData + y *img->widthStep); ptr[3*x+0]=setblue; ptr[3*x+1]=setgreen; ptr[3*x+2]=setred; } t = (double)cvGetTickCount() - t; g_PointerTime=g_PointerTime+t; }
関数を使った場合と、ポインタで直接いじった場合の差は以下のようになりました。
execution time(cvSet2D) = 3.85831 ms
execution time(Pointer) = 0.969397 ms
関数を使うと、オーバーヘッドはどうしても出てしまいますね。。。