Opencv第三章練習題答案

pamxy發表於2014-09-08

我的編譯環境是vs2012,opencv-2.4.9,要在附加依賴項中新增:opencv_core249d.lib opencv_highgui249d.lib opencv_imgproc249d.lib。也可以在程式碼裡面新增以下內容:

  1. #pragma comment(lib,"opencv_core249d.lib")  
  2. #pragma comment(lib,"opencv_highgui249d.lib")  
  3. #pragma comment(lib,"opencv_imgproc249d.lib")  


2.下面這個聯絡是幫助掌握矩陣型別。創造一個三通道二維矩陣,位元組型別,大小為100X100,並設定所有數值為0。

a.在矩陣中使用void cvCircle(CvArr* img,CvPoint center,int radius,CvScalar color,int thickness=1,int line_type=8,int shift=0)畫一個圓。

b.使用第2章所學的方法來顯示這幅影象。

CvMat* mat=cvCreateMat(100,100,CV_8UC3);
cvSetZero(mat);
cvCircle(mat,cvPoint(mat->width/2,mat->height/2),mat->width/3,CV_RGB(255,0,0) );

cvNamedWindow(winName,CV_WINDOW_AUTOSIZE);
cvShowImage(winName,mat);
cvWaitKey(0);



3.建立一個有用三個通道的二維位元組型別矩陣,大小為100X100,並將所有值賦為0。通過函式cvPtr2D將指標指向中間的通道(“”綠色“)。以(20,5)與(40,20)為頂點間畫一個綠色的長方形。

CvMat* mat=cvCreateMat(100,100,CV_8UC3);
cvZero(mat);
unsigned char* pMat=cvPtr2D(mat,0,0);
for (int i=0;i<mat->cols;i++)
{
	for (int j=0;j<mat->rows;j++)
	{
		pMat=cvPtr2D(mat,i,j);
			
		if (isThePointInRectangel(i,j)== true)
		{
			//使pMat指向綠色通道
			*(pMat+1)=255;
		}
	}
}

cvNamedWindow(winName,CV_WINDOW_AUTOSIZE);
cvShowImage(winName,mat);

cvWaitKey(0);
cvReleaseMat(&mat);
cvDestroyWindow(winName);



4.建立一個大小為100X100的三通道RGB影象。將它的元素全部置0。使用指標演算法以(20,5)與(40,20)為頂點繪製一個綠色平面。

<span style="white-space:pre">	</span>IplImage* img=cvCreateImage(cvSize(100,100),8,3);
	cvZero(img);
	for (int y=5;y<=20;y++)
	{
		unsigned char* pImg=(unsigned char*)(img->imageData+y*img->widthStep);

		for (int x=20;x<=40;x++)
		{
			//3個通道
			*(pImg+3 * x +1)=255;
			//或
			//pImg[3 * x +1]=255;
		}
	}

	cvNamedWindow(winName);
	cvShowImage(winName,img);
	cvWaitKey(0);

	cvReleaseImage(&img);
	cvDestroyWindow(winName);



5.練習使用感興趣區域(ROI)。建立一個210X210的單通道影象並將其歸0。在影象中使用ROI和cvSet()建立一個增長如金字塔狀的陣列。也就是:外部邊界為0,下一個內部邊界應該為20,再下一個內部邊界為40依此類推,直到最後內部值為200;所有的邊界應該為10個畫素的寬度。最後顯示這個圖形。

<span style="white-space:pre">	</span>int x=0;
	int y=0;
	int width=210;
	int height=210;
	int color=0;
	int edge=10;
	int raiseColor=20;
	int nBreakValue=200;

	IplImage* img=cvCreateImage(cvSize(width,height),IPL_DEPTH_8U,1);
	cvZero(img);

	while (true)
	{
		cvSetImageROI(img,cvRect(x,y,width,height) );
		cvSet(img,cvScalar(color) );
		x+=edge;
		y+=edge;
		width-=2*edge;
		height-=2*edge;
		color+=raiseColor;
		cvResetImageROI(img);

		if (color>nBreakValue)
		{
			break;
		}
	}

	cvNamedWindow(winName,CV_WINDOW_AUTOSIZE);
	cvShowImage(winName,img);
	cvWaitKey(0);

	cvReleaseImage(&img);
	cvDestroyWindow(winName);



6.為一個影象建立多個影象頭。讀取一個大小至少為100X100的影象。另建立兩個影象頭並設定它們的origion,depth,nChannels和widthStep屬性同之前讀取的影象一樣。在新的影象頭中,設定寬度為20,高度為30。最後,將imageData指標分別指向畫素(5,10)和(50,60)畫素位置。傳遞這兩個新的影象頭給cvNot()。最後顯示最初讀取的影象,在那個大影象中應該有兩個矩形,矩形內的值是原始值的求反值。

<span style="white-space:pre">	</span>int width=20;
	int height=30;
	
	IplImage* img=cvLoadImage("2.jpeg");
	int depth=img->depth;
	int channel=img->nChannels;
	int origin=img->origin;
	int widthStep=img->widthStep;

	IplImage* img1=cvCreateImageHeader(cvSize(width,height),depth,channel);
	IplImage* img2=cvCreateImageHeader(cvSize(width,height),depth,channel);
	img1->origin=origin;
	img2->origin=origin;
	img1->widthStep=widthStep;
	img2->widthStep=widthStep;

	img1->imageData=img->imageData+10* img->widthStep+5*img->nChannels;
	img2->imageData=img->imageData+60* img->widthStep+50*img->nChannels;

	cvNot(img1,img1);
	cvNot(img2,img2);

	cvNamedWindow(winName);
	cvShowImage(winName,img);
	cvWaitKey(0);

	cvReleaseImage(&img1);
	cvReleaseImage(&img2);
	cvReleaseImage(&img);
	cvDestroyWindow(winName);



7.使用cvCmp()建立一個掩碼。載入一個真實的影象。使用cvSplit()將影象分割成紅,綠,藍三個當通道影象。

a.找到並顯示綠圖。

b.克隆這個綠圖兩次(分別命名為clone1和clone2)。

c求出這個綠色平面的最大值和最小值。

d.將clone1的所有元素賦值為thresh=(unsigned char)((最大值-最小值)/2.0)。

e.將clone2所有元素賦值為0,然後呼叫函式cvCmp(green_image,clone1,clone2,CV_CMP_GE)。現在clone2將是一個標識綠圖中值超過thresh的掩碼影象。

f.最後,使用cvSubS(green_image,thresh/2,green_image,clone2)函式並顯示結果。

<span style="white-space:pre">	</span>const char* winImgPre="img_pre";
	const char* winImgG="img_Green";
	const char* winImgGA="img_Green_after";

	IplImage* img=cvLoadImage("2.jpeg");

	cvNamedWindow(winImgPre);
	cvShowImage(winImgPre,img);

	IplImage* imgR=cvCreateImage(cvSize(img->width,img->height),img->depth,1);
	IplImage* imgG=cvCreateImage(cvSize(img->width,img->height),img->depth,1);
	IplImage* imgB=cvCreateImage(cvSize(img->width,img->height),img->depth,1);

	cvSplit(img,imgG,imgB,imgR,NULL);

	cvNamedWindow(winImgG);
	cvShowImage(winImgG,imgG);

	IplImage* clone1=cvCloneImage(imgG);
	IplImage* clone2=cvCloneImage(imgG);

	double maxNum,minNum;
	cvMinMaxLoc(imgG,&minNum,&maxNum);
	cout<<"MinNum in imgG:"<<minNum<<endl;
	cout<<"MaxNum in imgG:"<<maxNum<<endl;

	double scalar=(maxNum-minNum)/2;
	cvSet(clone1,cvScalar(scalar) );

	cvSetZero(clone2);

	cvCmp(imgG,clone1,clone2,CV_CMP_GE);

	cvSubS(imgG,cvScalar(scalar/2),imgG,clone2);

	cvNamedWindow(winImgGA);
	cvShowImage(winImgGA,imgG);
	cvWaitKey(0);

	cvReleaseImage(&img);
	cvReleaseImage(&imgG);
	cvDestroyWindow(winName);
	cvDestroyWindow(winImgG);
	cvDestroyWindow(winImgGA);
	cvReleaseImage(&clone2);



8.建立一個結構,結構中包含一個整數,一個CvPoint和一個CvRect;稱結構為"my_struct"。

a.寫兩個函式:void write_my_struct(CvFileStorage* fs,const char* name,my_struct* ms)和void read_my_struct(CvFileStorage* fs,CvFileNode* ms_node,my_struct* ms)。用它們讀、寫my_struct。

b.建立一個元素為my_struct結構體且長度為10的陣列,並將陣列寫入磁碟和從磁碟讀入記憶體。

#include "highgui.h"
#include <iostream>

using namespace std;

typedef struct 
{
	int i;
	CvPoint pt;
	CvRect rect;
}my_struct;

void write_my_struct(CvFileStorage* fs,const char* name,my_struct* ms)
{
	assert(fs !=0);
	cvWriteInt(fs,"i",ms->i);
	cvStartWriteStruct(fs,"pt",CV_NODE_SEQ);
	cvWriteInt(fs,0,ms->pt.x);
	cvWriteInt(fs,0,ms->pt.y);
	cvEndWriteStruct(fs);
	cvStartWriteStruct(fs,"rect",CV_NODE_SEQ);
	cvWriteInt(fs,0,ms->rect.x);
	cvWriteInt(fs,0,ms->rect.y);
	cvWriteInt(fs,0,ms->rect.width);
	cvWriteInt(fs,0,ms->rect.height);
	cvEndWriteStruct(fs);
}

void read_my_struct(CvFileStorage* fs,CvFileNode* ms_node,my_struct* ms)
{
	assert(fs !=0);
	ms->i=cvReadIntByName(fs,0,"i",0);
	CvSeq* s=cvGetFileNodeByName(fs,0,"pt")->data.seq;
	ms->pt.x=cvReadInt((CvFileNode*)cvGetSeqElem(s,0) );
	ms->pt.y=cvReadInt((CvFileNode*)cvGetSeqElem(s,1) );

	CvSeq* s1=cvGetFileNodeByName(fs,0,"rect")->data.seq;
	ms->rect.x=cvReadInt((CvFileNode*)cvGetSeqElem(s1,0) );
	ms->rect.y=cvReadInt((CvFileNode*)cvGetSeqElem(s1,1) );
	ms->rect.width=cvReadInt((CvFileNode*)cvGetSeqElem(s1,2) );
	ms->rect.height=cvReadInt((CvFileNode*)cvGetSeqElem(s1,3) );

	//輸出讀取的結果
	cout<<"my_struct:"<<endl;
	cout<<"i:"<<ms->i<<endl;
	cout<<"pt:("<<ms->pt.x<<","<<ms->pt.y<<")"<<endl;
	cout<<"rect:("<<ms->rect.x<<","<<ms->rect.y<<","<<ms->rect.width<<","<<ms->rect.height<<endl;
}

<span style="white-space:pre">	</span>CvFileStorage* fs=cvOpenFileStorage("cfg.xml",0,CV_STORAGE_WRITE);
	my_struct ms;
	ms.i=100;
	ms.pt.x=10;
	ms.pt.y=20;
	ms.rect.x=30;
	ms.rect.y=40;
	ms.rect.width=50;
	ms.rect.height=60;
	write_my_struct(fs,NULL,&ms);
	cvReleaseFileStorage(&fs);

	//往xml檔案中讀資料
	CvFileStorage* fs1=cvOpenFileStorage("cfg.xml",0,CV_STORAGE_READ);
	my_struct ms1;
	read_my_struct(fs1,NULL,&ms1);
	cvReleaseFileStorage(&fs1);
	
	cin.get();


相關文章