2008年7月20日 星期日

資料結構操作與運算-通道的分割,合併與混合

通道的分割與合併,用到的是cvSplit()與cvMerge(),它可以把多通道分割成單通道,並且也可以把單通道都合併成多通道,下面的實作為利用通道分割與合併,將該圖的RGB值分開,並且個別的顯示出來,可以知道一張圖片RGB值的分佈狀況.

擷取RGB圖片,通道的分割與合併
#include <cv.h>
#include <highgui.h>

int main()
{
    IplImage *Image1;
    IplImage *RedImage,*GreenImage,*BlueImage;
    IplImage *Channel1,*Channel2,*Channel3;
    CvSize Size1;
    Image1=cvLoadImage("grotto.jpg",1);
    Size1=cvGetSize(Image1);

    Channel1=cvCreateImage(Size1,IPL_DEPTH_8U,1);
    Channel2=cvCreateImage(Size1,IPL_DEPTH_8U,1);
    Channel3=cvCreateImage(Size1,IPL_DEPTH_8U,1);
    cvSplit(Image1,Channel1,Channel2,Channel3,0);

    BlueImage=cvCreateImage(Size1,IPL_DEPTH_8U,3);
    GreenImage=cvCreateImage(Size1,IPL_DEPTH_8U,3);
    RedImage=cvCreateImage(Size1,IPL_DEPTH_8U,3);
    cvMerge(Channel1,0,0,0,BlueImage);
    cvMerge(0,Channel2,0,0,GreenImage);
    cvMerge(0,0,Channel3,0,RedImage);

    cvNamedWindow("Red pic",1);
    cvShowImage("Red pic",RedImage);
    cvNamedWindow("Green pic",1);
    cvShowImage("Green pic",GreenImage);
    cvNamedWindow("Blue pic",1);
    cvShowImage("Blue pic",BlueImage);

    cvWaitKey(0);
}

原始圖片:


執行結果:


上面的程式碼先讀取了圖檔,再創立了空的uchar型別單通道IplImage資料結構,各分成三個通道的資料結構,利用cvSplit()將圖形的通道分割,因此Channel1,Channel2,Channel3都取得數值了,而cvSplit()第五個引數為第四個通道的資料結構,因為是讀取一般的圖檔,只需要三個通道,所以將它設置為0,再來是創立三個通道為三的RGB圖形IplImage資料結構,利用cvMerge()置入RGB顏色個別的通道,不需要用到的通道就設為0,因此,RGB圖片就順利被擷取出來了.


對於多通道的混合,就要用到cvMixChannels()這個函式啦,他可做到連續多張輸出,輸入的圖片它的所有通道數做隨意的配置但是它的函式還是有些遊戲規則要注意的.

通道混合的實作
#include <cv.h>
#include <highgui.h>


int from_to[]={3,0
                     ,2,1
                     ,1,2
                     ,0,3};
int main()
{
    IplImage *Image1,*Image2;
    IplImage *GrayRGBImage;

    CvSize Size1;
    Image1=cvLoadImage("grotto.jpg",1);
    Image2=cvLoadImage("grotto.jpg",0);
    Size1=cvGetSize(Image1);
    GrayRGBImage=cvCreateImage(Size1,IPL_DEPTH_8U,4);

    CvArr const *src[]={Image1,Image2};
    CvArr *dst[]={GrayRGBImage};

    cvMixChannels(src,2,dst,1,from_to,4);

    cvNamedWindow("MixChannels",1);
    cvShowImage("MixChannels",GrayRGBImage);
    cvWaitKey(0);
}

執行結果:


上面將grotto.jpg的彩圖跟灰階圖分別用cvLoadImage()讀出來,而對於Image2的灰階圖,cvLoadImage()這個函式將它的灰階值存成了三個通道,接著再用IplImage資料結構創立一個自定義的通道格式"灰階+紅色+綠色+藍色",這邊,cvMixChannels()的函式內,目標圖(src)跟輸出圖(dst)都要放在一維陣列內,因為他可以對連續多張圖片做通道的混合,第一個引數為輸入CvArr結構的圖形陣列,第二個引數為他輸入的圖形個數,第三個為輸出的CvArr結構圖形陣列,再來是輸出的圖形個數,下一個引數,為通道交換的規則,在from_to的陣列內,數據的意義以兩個為一組,分別為將輸入的第三個通道置入輸出的第零的通道,第二個通道放第一個通道,第一個通道放第二個通道,第零個通道放入第三個通道,依此類推,由於輸入為兩張圖片,一張全彩圖,一張灰階圖,總通道數為4,灰階圖的為單通道uchar型別的矩陣型態,這邊from_to就是用輸出跟輸入的總通道數做交換的,第五個引數為被選取多少通道數,有四個通道被混合,因此from_to的陣列空間就為8.

from_to陣列的對應

輸入圖形共4個通道,輸出圖形亦是4個通道,選取了四組通道被混合

cvSplit()
將多通道的圖形分割成單通道的圖形,第一個引數為輸入目標多通道圖形結構,第二,三,四,五個引數為輸出通道的圖形資料結構,輸出必須放單通道uchar型別的IplImage或CvMat矩陣資料結構
cvSplit(輸入多通道IplImage或CvMat資料結構圖形,輸出單通道IplImage或CvMat資料結構,輸出單通道IplImage或CvMat資料結構,輸出單通道IplImage或CvMat資料結構,輸出單通道IplImage或CvMat資料結構)

cvMerge()
合併單通道矩陣為成為多通道的圖形,前四個引數為單通道uchar型別的資料結構,第五個引數為輸出IplImage資料結構或CvMat結構圖形
cvMerge(輸入單通道IplImage或CvMat資料結構,輸入單通道IplImage或CvMat資料結構,輸入單通道IplImage或CvMat資料結構,輸入單通道IplImage或CvMat資料結構,輸出多通道IplImage或CvMat資料結構圖形)

cvMixChannels()
將多張圖形的通道做混合,輸入及輸出支援多張圖形,因此要放置在圖形陣列上,第一個引數為輸入CvArr圖形陣列,第二個為輸入圖形的個數,第三個為輸出CvArr圖形陣列,第四個為輸出圖形陣列的個數,第五個為通道數混合方式的陣列,第五個是被用到的總通道數
cvMixChannels(CvArr輸入圖形陣列,總輸入圖形數目,CvArr輸出圖形陣列,總輸出圖形數目,混合通道方式數據陣列,被混合的通道數)



6 意見:

匿名 提到...

您好:
看了您的文章受益良多。
請教一個問題,Run了這個實驗,您的程式結果是RGB三張圖顯現,而我的結果卻是CMY三張圖顯現,請問是什麼原因呢?

維辰 提到...

你好:
請問一下,如果我想要用webcam擷取連續影像實作(rgb轉ycbcr這部分部用內建涵式)要如何處理連續秀出影響

ZHChen 提到...

在cvCreateImage與cvMerge之間,用cvZero先把數據歸零,就不會有CMY顯示的問題了

學生 提到...

我目前是學生,對OpenCV感到興趣,從一開始入門
都是參考您的資料,讓我受益良多在此先感謝您。

我想請問Open CV 可以處理HDR的影像嗎?
因為目前讀進來的圖片我們可以簡單的取到每個Pixel的RGB
但HDR他有RGBE所以我想了解有沒有辦法取得E??

Ian 提到...

謝謝版大;我目前在做專題;每天再參考你的教學~大感激
希望版大能提供更多更詳細的解說與教學^^

Unknown 提到...

你好 我想問為什麼我分離出的顏色會是(粉紅 青 黃) 謝謝

Copyright 2008-2009,yester