IplImage,CvMat圖形矩陣空間
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
int main()
{
IplImage *Image1;
IplImage *Image2;
CvMat *Matrix1;
CvSize Size1;
Image1=cvLoadImage("footpath.jpg",1);
Size1=cvGetSize(Image1);
Image2=cvCreateImageHeader(Size1,IPL_DEPTH_8U,3);
Matrix1=cvCreateMatHeader(Size1.height,Size1.width,CV_8UC3);
cvGetMat(Image1,Matrix1);
cvFlip(Matrix1,Matrix1,1);
cvGetImage(Matrix1,Image2);
cvNamedWindow("footpath (Flip)",1);
cvShowImage("footpath (Flip)",Image2);
cvWaitKey(0);
cvReleaseImage(
&
Image1);cvReleaseImageHeader(
&
Image2);cvReleaseMatHeader(
&
Matrix1);cvDestroyWindow("footpath (Flip)");
}
原始圖片:

執行結果:
這邊的執行結果是將圖形做翻轉(Flip)的動作,利用標頭給定標頭轉換CvMat資料結構矩陣空間及IplImage的矩陣空間,但實際上它們的矩陣空間是共用的,Image1的矩陣空間跟Image2跟CvMat共用相同的記憶體位址,都是同一個imageData或CvMat的data,而cvFlip()他可以對CvMat及IplImage資料結構進行翻轉.cvFlip()第三個參數如果數值為0,為水平翻轉,數值為1,為垂直翻轉,數值為-1則是水平+垂直翻轉
IplImage,CvMat圖形矩陣空間2
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
int main()
{
IplImage *Image1;
IplImage *Image2;
CvMat *ROIMatrix;
CvRect Rect1;
CvSize Size1;
Image1=cvLoadImage("footpath.jpg",1);
Size1=cvGetSize(Image1);
Image2=cvCreateImage(Size1,IPL_DEPTH_8U,3);
ROIMatrix=cvCreateMat(150,150,CV_8UC3);
Rect1=cvRect(300,150,150,150);
cvGetSubRect(Image1,ROIMatrix,Rect1);
cvRepeat(ROIMatrix,Image2);
cvNamedWindow("Image Repeat",1);
cvShowImage("Image Repeat",Image2);
cvWaitKey(0);
cvReleaseImage(
&
Image1);cvReleaseImageHeader(
&
Image2);cvReleaseMat(
&
ROIMatrix);cvDestroyWindow("Image Repeat");
}
執行結果:
這邊是以ROI的方式由IplImage資料結構取得CvMat資料結構150*150的區塊,而cvGetSubRect()出來的結果,ROIMatrix跟Image1共用記憶體空間,只不過ROIMatrix取得了Rect資料結構所選擇的區段,而用了cvRepeat(),Image2則是沒有跟Image1跟ROIMatrix共用記憶體區段.
在這邊,前兩個程式碼矩陣空間標頭宣告都是CV_8U3C,而它因為是矩陣空間(RawData)的轉移,所以它的內部資料空間的型別並不會因為標頭宣告而改變,在圖形,矩陣上的空間使用的型別都會是uchar,也可以直接將標頭矩陣的種類改成CV_32FC3,但是這樣會造成標頭資訊與內儲資料空間不符,因此不建議程式這麼做,而如果要改變矩陣空間的型別,可以使用cvConvertScale()來做轉換.
IplImage的空間型別轉換實作
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
int Scale=1;
int Shift=0;
int main()
{
IplImage *Image1;
IplImage *Image2;
IplImage *Image3;
CvSize Size1;
Image1=cvLoadImage("footpath.jpg",1);
Size1=cvGetSize(Image1);
Image2=cvCreateImage(Size1,IPL_DEPTH_32F,3);
Image3=cvCreateImage(Size1,IPL_DEPTH_8U,3);
cvConvertScale(Image1,Image2,Scale,Shift);
printf("%.1f ",cvGet2D(Image2,50,50).val[0]);
printf("%.1f ",cvGet2D(Image2,50,50).val[1]);
printf("%.1f ",cvGet2D(Image2,50,50).val[2]);
Shift=-100;
cvConvertScale(Image2,Image3,Scale,Shift);
cvNamedWindow("footpath",1);
cvShowImage("footpath",Image3);
cvWaitKey(0);
cvReleaseImage(
&
Image1);cvReleaseImage(
&
Image2);cvReleaseImage(
&
Image3);cvDestroyWindow("footpath");
}
執行結果:
cvConvertScale()可以對任何圖形空間的型別來做轉換,因此不會因為uchar型別0~255的限制而超出範圍了,而cvConvertScale()亦可以使用再IplImage資料結構及CvMat資料結構上,但必須要與原圖的通道數及大小一致,第一個引數目標圖形,第二個引數為輸出圖形,第三個為目標圖形純量積相乘,第四的為全部顏色位移量,公式為
OutputPic[i][j]=Scale*Convert(InputPic[i][j])+Shift for all i=0,1,2,3...height,j=0,1,2,3...width
不過,要記得將轉換型別的格式由浮點樹形別轉換回uchar,要不然cvShowImage()就無法顯示,而cvSaveImage()執行出來的圖檔也會是錯誤的.
(1)IplImage,CvMat資料結構共用圖形記憶體空間

(2)cvGetSubRect()擷取記憶體區段

前面IplImage擷取ROI區段也是同樣的方式
cvGetMat()
給定CvMat結構的標頭,可以取得目標IplImage結構或是CvMat結構的圖形資料空間.而與目標結構共用記憶體.
cvGetMat(目標IplImage結構或CvMat結構,CvMat標頭結構)
cvGetImage()
給定IplImage資料結構的標頭,可以取得目標IplImage結構或是CvMat結構的圖形資料空間.而與目標結構共用記憶體.
cvGetImage(目標IplImage結構或CvMat結構,IplImage標頭結構)
cvFlip()
對目標IplImage資料結構或CvMat資料結構做翻轉的動作,第一個引數為目標IplImage資料結構或CvMat結構,第二個為翻轉後放置結果的IplImage或CvMat資料結構,第三個引數為翻轉方式,0為水平翻轉,1為垂直翻轉,-1為水平+垂直翻轉.
cvFlip(目標IplImage或CvMat資料結構,輸出IplImage或CvMat資料結構,翻轉方式數據)
cvGetSubRect()
擷取區塊子圖,跟ROI使用方式很類似,擷取出來的結果會放在CvMat資料結構上,第一個引數為目標IplImage資料結構或CvMat資料結構,第二個引數為輸出的CvMat資料結構,第三的引數為選定的位置跟大小的CvRect資料結構.
cvGetSubRect(目標IplImage或CvMat資料結構,輸出的CvMat資料結構,選定的CvRect資料結構)
cvRepeat()
重複目標圖片,直到被選定的結構空間填滿為止,這邊兩個引數都可以用IplImage或CvMat資料結構,而也可以第一張圖比第二張大,但是看不到重複的效果.
cvRepeat(目標IplImage或CvMat資料結構,輸出IplImage資料結構或CvMat結構)
cvConvertScale()
可以任意轉換矩陣資料空間游標頭檔定義的的型別,可以用IplImage資料結構及CvMat資料結構,第一個引數為目標結構,第二個引數為輸出結構,第三個為矩陣空間的純量積(Scalar multiplication),也就是對矩陣乘上某倍數,第四個為數據大小的位移,也就是對每個矩陣的數據加上某數據
cvConvertScale(目標IplImage資料結構或CvMat結構,輸出IplImage結構或CvMat結構,矩陣純量數據,矩陣位移數據)
1 意見:
您好,我是根據您的網站一一往下學習CV的學生,再到這二題的時候(也就是重複貼上的那題),我將您的程式完整複製過去執行,出現了以下錯誤:
於 0x7645c41f 的 text.exe 中第一個可能發生的例外狀況: Microsoft C++ 在記憶體位置 0x0047f948,發生例外狀況: cv::Exception
我只能猜測跟記憶體有關,一行行檢查發現出錯在cvRepeat執行時,我完全沒有改動您的程式,想要請問這樣的問題該怎麼解決,我是不是在其他地方做錯什麼?
張貼留言