2008年10月7日 星期二

OpenCV統計應用-總和,計算非零

再來就是一些計數的函式啦,下面簡單的介紹一張圖形,所有數值總和以及圖形上所有非0的計算,在一些圖形數值的量測方面,稍微具有一些實質的意義.

簡單cvSum()使用
#include <cv.h>
#include <highgui.h>
#include <stdio.h>

int main()
{
    IplImage *Image1=cvLoadImage("grotto.jpg",1);
    CvScalar Scalar1;
    Scalar1 = cvSum(Image1);

    printf("Blue Channel Sum is : %.f\n",Scalar1.val[0]);
    printf("Green Channel Sum is : %.f\n",Scalar1.val[1]);
    printf("Red Channel Sum is : %.f\n",Scalar1.val[2]);


    cvNamedWindow("grotto",1);
    cvShowImage("grotto",Image1);
    cvWaitKey(0);
}

原始圖片:


執行結果:


cvSum()是計算所有圖片每個通道數據的總和,因此在這個通道為3的RGB圖,所有的總和都被計算在CvScalar資料結構上面了,cvSum()輸入為IplImage或CvMat資料結構,輸出為CvScalar的資料結構,裡面存放著RGB的總和數值,接著就是cvContNonZero()的使用.

簡單cvCountNonZero()使用
#include <cv.h>
#include <highgui.h>
#include <stdio.h>

int main()
{
    IplImage *Image1=cvLoadImage("grotto_Threshold.jpg",0);

    printf("Thresholding Non Zero is : %d\n",cvCountNonZero(Image1));

    cvNamedWindow("grotto",1);
    cvShowImage("grotto",Image1);
    cvWaitKey(0);
}

原始圖片:


執行結果:


cvCountNonZero()為計算非0的個數,只能使用在單通道的圖形,而且對於這個函式在黑白圖的使用上會比較具有意義,由於黑白圖非0即1因此計算出非0的個數同時也算出了1的個數,而cvCountNonZero(),以及cvSum()也可以支援COI(Color Of Interesting)以及ROI(Region Of Interesting)的使用,使用方式如下

cvCountNonZero()及cvSum()的ROI,COI
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


int main()
{
    IplImage *Image1=cvLoadImage("grotto.jpg",1);

    cvSetImageROI(Image1,cvRect(100,100,100,100));

    cvSetImageCOI(Image1,1);
    printf("Blue Channel Non Zero is : %d\n",cvCountNonZero(Image1));
    printf("Blue Channel Sum is : %.f\n",cvSum(Image1).val[0]);

    cvSetImageCOI(Image1,2);
    printf("\nGreen Channel Non Zero is : %d\n",cvCountNonZero(Image1));
    printf("Green Channel Sum is : %.f\n",cvSum(Image1).val[0]);

    cvSetImageCOI(Image1,3);
    printf("\nRed Channel Non Zero is : %d\n",cvCountNonZero(Image1));
    printf("Red Channel Sum is : %.f\n",cvSum(Image1).val[0]);

    cvNamedWindow("grotto(ROI)",1);
    cvShowImage("grotto(ROI)",Image1);
    cvResetImageROI(Image1);
    cvNamedWindow("grotto",1);
    cvShowImage("grotto",Image1);

    cvWaitKey(0);
}

執行結果:


對於一個被選定COI的他會對於特定顏色做統計,cvCountNonZero()以及cvSum()亦是如此,而被選定ROI他會對於特定的區域做計算,因此上面的結果會是被選定的區域,加上被選定的顏色,他所計算出來的統計結果,而COI選定的顏色後,因為是單通道的,所以cvSum()計算出來的結果會被放在CvScalar資料結構val[0]的位置,這邊用cvSum(Image1).val[0]表示直接存取CvScalar資料結構val[0]的數據.

cvSum()
計算所有通道數據的總和,計算出來的結果會回傳放在CvScalar資料結構上,如果是使用單通道或是COI的話會放在CvScalar資料結構val[0]上面.輸入的引數為IplImage資料結構或CvMat資料結構.
cvSum(輸入IplImage或CvMat資料結構)

cvCountNonZero()
計算所有非0數據的總和,只支援單通道或是COI,輸入為IplImage資料結構或CvMat資料結構,輸出為int變數型別.
cvCountNonZero(輸入IplImage或CvMat資料結構)



OpenCV統計應用-基本統計直方圖

在統計學裡面,最基本影像處理的應用,就是統計直方圖了,它可以將一張圖片的色彩結構統計起來,對於一張圖片的R值,G值,B值或灰階做統計計算,或者是,轉換到另一個色彩空間,將圖形做量化及統計的計算,在OpenCV裡面,也有不少統計直方圖的計算,並且可以將它圖表化,呈現出統計的概況.

基本統計直方圖計算
#include <cv.h>
#include <highgui.h>
#include <stdio.h>

int BlueHistogramData[256]={0};
int GreenHistogramData[256]={0};
int RedHistogramData[256]={0};
int GrayLevelHistogramData[256]={0};

int main()
{
    IplImage *Image1=cvLoadImage("waterfall.jpg",1);
    CvScalar Scalar1;
    int BlueColor,GreenColor,RedColor,GrayLevelColor;

    for(int i=0;i<Image1->height;i++)
    {
        for(int j=0;j<Image1->width;j++)
        {

            Scalar1=cvGet2D(Image1,i,j);
            BlueColor=(int)Scalar1.val[0];
            GreenColor=(int)Scalar1.val[1];
            RedColor=(int)Scalar1.val[2];
            GrayLevelColor=(int) (0.299*RedColor+0.587*GreenColor+0.114*BlueColor);

            BlueHistogramData[BlueColor]++;
            GreenHistogramData[GreenColor]++;
            RedHistogramData[RedColor]++;
            GrayLevelHistogramData[GrayLevelColor]++;

        }
    }
    printf("Red\tGreen\tBlue\tGrayLevel\n");
    for(int i=0;i<256;i++)
    {

        printf("%d\t%d\t%d\t%d\t\n",RedHistogramData[i],GreenHistogramData[i],BlueHistogramData[i],GrayLevelHistogramData[i]);
    }

    cvNamedWindow("waterfall",1);
    cvShowImage("waterfall",Image1);
    cvWaitKey(0);
}

原始圖片:


執行結果:


上面的程式碼,就是將RGB值做統計,將R值,G值,B值累加在0~255的範圍裡,因此就可以知道這張圖的色彩分布的結構,灰階圖亦然,而OpenCV亦可以做到圖表的呈現的方式,利用的是繪圖函式來實作,用cvLine()或是cvRectangle()就可以做到統計值方圖的繪製,OpenCV在統計直方圖製作部分有一個CvHistogram的資料結構可以實作,而下面這個,則是直接將上面的程式碼修改繪製上去的統計值方圖製作.

統計直方圖計算與繪製
#include <cv.h>
#include <highgui.h>
#include <stdio.h>


int BlueHistogramData[256]={0};
int GreenHistogramData[256]={0};
int RedHistogramData[256]={0};
int GrayLevelHistogramData[256]={0};


int main()
{
    IplImage *Image1=cvLoadImage("waterfall.jpg",1);
    IplImage *BlueHistogramImage,*GreenHistogramImage,*RedHistogramImage;
    IplImage *GrayLevelHistogramImage;

    BlueHistogramImage=cvCreateImage(cvSize(256,250),IPL_DEPTH_8U,3);
    GreenHistogramImage=cvCreateImage(cvSize(256,250),IPL_DEPTH_8U,3);
    RedHistogramImage=cvCreateImage(cvSize(256,250),IPL_DEPTH_8U,3);
    GrayLevelHistogramImage=cvCreateImage(cvSize(256,250),IPL_DEPTH_8U,3);

    BlueHistogramImage->origin=1;
    GreenHistogramImage->origin=1;
    RedHistogramImage->origin=1;
    GrayLevelHistogramImage->origin=1;

    CvScalar Scalar1;
    int BlueColor,GreenColor,RedColor,GrayLevelColor;

    for(int i=0;i<Image1->height;i++)
    {
        for(int j=0;j<Image1->width;j++)
        {

            Scalar1=cvGet2D(Image1,i,j);
            BlueColor=(int)Scalar1.val[0];
            GreenColor=(int)Scalar1.val[1];
            RedColor=(int)Scalar1.val[2];
            GrayLevelColor=(int) (0.299*RedColor+0.587*GreenColor+0.114*BlueColor);

            BlueHistogramData[BlueColor]++;
            GreenHistogramData[GreenColor]++;
            RedHistogramData[RedColor]++;
            GrayLevelHistogramData[GrayLevelColor]++;

        }
    }
    for(int i=0;i<255;i++)
    {
        cvLine(BlueHistogramImage,cvPoint(i,BlueHistogramData[i]/10),cvPoint(i,0),CV_RGB(0,0,255));
        cvLine(GreenHistogramImage,cvPoint(i,GreenHistogramData[i]/10),cvPoint(i,0),CV_RGB(0,255,0));
        cvLine(RedHistogramImage,cvPoint(i,RedHistogramData[i]/10),cvPoint(i,0),CV_RGB(255,0,0));
        cvLine(GrayLevelHistogramImage,cvPoint(i,GrayLevelHistogramData[i]/10),cvPoint(i,0),CV_RGB(128,128,128));
    }

    cvNamedWindow("waterfall",1);
    cvShowImage("waterfall",Image1);
    cvNamedWindow("Blue Histogram",1);
    cvShowImage("Blue Histogram",BlueHistogramImage);
    cvNamedWindow("Green Histogram",1);
    cvShowImage("Green Histogram",GreenHistogramImage);
    cvNamedWindow("Red Histogram",1);
    cvShowImage("Red Histogram",RedHistogramImage);
    cvNamedWindow("GrayLevel Histogram",1);
    cvShowImage("GrayLevel Histogram",GrayLevelHistogramImage);

    cvWaitKey(0);
}

執行結果:


在繪製圖形的時候,亦要開啟圖表的空間,IplImage資料結構,在將IplImage資料結構的origin設為1,為Window XP預設圖形起始點,這部份在"資料結構操作與運算-IplImage資料結構"有詳細的介紹,再來就是讀取RGB值做統計,以及使用cvLine()做繪製,cvLine()的繪製方法則是在"OpenCV繪圖的實作-cvLine,cvRectangle"有介紹到,而CvHistogram資料結構也是使用類似上面的原理,在OpenCV裡面,統計直方圖的部分還是需要自己動手畫,沒有很方便的函式可以直接實作出視覺化圖形的呈現.



Copyright 2008-2009,yester