opencv圖片上如何顯示兩個小圖片

勿在浮砂築高臺發表於2014-11-23
這個問題產生於第四章習題1.b我琢磨了大半天,但是最終明白了。
首先解釋一下cvCreateImage()與cvCreateImageHeader()兩個函式的區別
         這兩個函式引數都是一樣的,這兩個函式的區別是cvCreateImage 除了分配影象頭之外,還分配影象資料,而cvCreateImageHeader僅僅是分配影象頭,並沒有分配影象資料。之所以被稱為圖片頭,我想是因為沒有屬於自己的記憶體空間資料,但是imagedata可以指向其他的影象資料區,或者呼叫void cvSetData( CvArr* arr, void* data, int step )。詳細區別,百度一下...........
進入正題:   
  IplImage *unit =cvCreateImage(cvSize(frame->width * 2,frame->height),frame->depth,3);
  IplImage *m_1  = cvCreateImageHeader(cvSize(frame->width ,frame->height),frame->depth,3);
  建立了一個寬度是兩倍幀寬的影象,並分配記憶體。 建立了一個幀寬的影象頭,沒有自己的資料區。
m_1->widthStep = unit->widthStep;                                    //重要啦。。。。
m_1->imageData = unit->imageData;
cvCopy(frame,m_1);
m_1->imageData = unit->imageData+frame->widthStep;
cvCopy(frame,m_1);
這樣就可以在一個圖片上,顯示兩個相同的影象。

 
問題來了,為什麼是m_1->widthStep = unit->widthStep 而不是m_1->widthStep = frame->widthStep
這是記憶體上資料排列順序的問題。我們可以這樣理解首先讓影象頭指到大影象的資料開始處,先拷貝一行畫素的資料,然後第二行資料肯定要拷貝到當前的正下方,而不能順著繼續存放。那麼就要有跳躍的存放,跳躍的寬度就一個frame->widthStep。但是我們一定要告知m_1的屬性widthStep。一般情況下widthStep == width *nChannels,但是這是普通的情況,有時一行畫素後會有垃圾區域,這就導致widthStep != width *nChannels。這時我們就屬於後一種情況,我們不能把有效資料存放到垃圾區域,就要有一個標誌widthStep,標示影象寬度真正大小。當存放了width *nChannels,就要跳躍(widthStep-width *nChannels)多個記憶體區,接著存放下一行畫素資料。這裡如果
m_1->widthStep = frame->widthStep   相當於(frame->widthStep-frame->width *nChannels) == 0跳躍寬度為0,這肯定不對。所以m_1->widthStep =frame->widthStep *2 ,也即m_1->widthStep = unit->widthStep 才對。

相關文章