2008年7月4日 星期五

資料結構操作與運算-IplImage資料結構(2)

上一篇的程式碼列出了IplImage主要用的變數型別,基本上,有這些資訊就夠用了,而IplImage實際上有那些變數型別呢?請看以下列表



+號以下代表IplImage可用變數型別,-號以下則代表著OpenCV少用,或甚至不用的變數型別.

再來,是用cvLoadImage()來實作IplImage資料結構影像處理相關的演算法.

IplImage資料結構灰階的實作
#include <cv.h>
#include <highgui.h>
#include <stdio.h>

uchar Blue[640][480];
uchar Green[640][480];
uchar Red[640][480];
uchar Gray[640][480];

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

    /* Load Image RGB Values */
    for(int i=0;i<image1->height;i++)
    {
        for(int j=0;j<image1->widthStep;j=j+3)
        {
            Blue[i][(int)(j/3)]=Image1->imageData[i*Image1->widthStep+j];
            Green[i][(int)(j/3)]=Image1->imageData[i*Image1->widthStep+j+1];
            Red[i][(int)(j/3)]=Image1->imageData[i*Image1->widthStep+j+2];
        }
    }

    /* Implement Algorithms */
    for(int i=0;i<image1->height;i++)
    {
        for(int j=0;j<image1->width;j++)
        {
            Gray[i][j]=(uchar)(0.299*Red[i][j] + 0.587*Green[i][j] + 0.114*Blue[i][j]);
            Red[i][j]=Gray[i][j];
            Green[i][j]=Gray[i][j];
            Blue[i][j]=Gray[i][j];
        }
    }

    /* Save Image RGB Values */
    for(int i=0;i<image1->height;i++)
    {
        for(int j=0;j<image1->widthStep;j=j+3)
        {
            Image1->imageData[i*Image1->widthStep+j]=Blue[i][(int)(j/3)];
            Image1->imageData[i*Image1->widthStep+j+1]=Green[i][(int)(j/3)];
            Image1->imageData[i*Image1->widthStep+j+2]=Red[i][(int)(j/3)];
        }
    }

    cvSaveImage("ghyll_gray.jpg",Image1);
    cvNamedWindow("Gray Level",1);
    cvShowImage("Gray Level",Image1);
    cvWaitKey(0);

    cvReleaseImage(&Image1);
    cvDestroyWindow("Gray Level");
}

原始圖片:


執行結果:
(1)


(2)Gray=(Red+Green+Blue)/3,錯誤的灰階結果


上面的程式碼分成三部分
1.imageData轉RGB(Load Image RGB Values)
2.RGB演算法實作(Implement Algorithms)
3.RGB轉imageData(Save Image RGB Values)
中間那部分的灰階是用轉灰階的演算法實作出來的,灰階演算法轉換並不是Gray=(Red+Green+Blue)/3,因為人的眼睛看到的色域範圍並不是紅綠藍各256的,因為人的眼睛對於能看見綠色的比率比較高,佔58%,對人來講能看見綠色的範圍佔快60%而相對的紅色跟藍色的能看見的區域就比較少,用加起來除以3將會是不正確的結果.

對於一般學術論文,創造新的演算法,或是影像處理相關作業演算法實作,都可以藉由這種方式來對IplImage資料結構讀取RGB值,就如同中通濾波器,轉灰階,小波轉換等演算法實作都可以在 /* Implement Algorithms */下面的for迴圈製作,接著將它轉回IplImage資料結構,存成圖檔,時間複雜度也只是O(n2)而已,不會造成浪費太多的時間,而OpenCV可以做到的強大功能是,大部分的圖檔格式都可以開啟做轉換,經由演算法處理做更多的應用.



8 意見:

Unknown 提到...

hi,yester
uchar Gray[640][340];
改为
uchar Gray[640][480];
?是不是笔误?还是有特殊用意?

wa114040@gmail.com 提到...

筆誤
Thanks

匿名 提到...

这么转灰度图,通道数没有变,怎么将图像变为灰度的单通道图呢

學習筆記 提到...

文中提到(2)Gray=(Red+Green+Blue)/3,錯誤的灰階結果
應該是資料溢位了,順便附上程式碼片段
Gray[i][j]=(uchar)(Red[i][j]/3.0 + Green[i][j]/3.0 + Blue[i][j]/3.0);

匿名 提到...

hi yester,
the code "image1" should better be "Image1", or the program will report error.

匿名 提到...

我複製執行
出現error C2065: 'image1' : 未宣告的識別項
error C2227: '->widthStep' 的左邊必須指向類別/結構/等位/泛型型別
是哪邊要修改???

逍遙文 提到...

image1改為Image1即可!
只是筆誤~

阿彥 提到...

您好!
我執行後會出現
"於 0x773115ee 的 1112.exe 中發生未處理的例外狀況: 0xC0000005: 讀取位置 0x0000002c 時發生存取違規"

請問該怎麼解決呢@@??? 謝謝

Copyright 2008-2009,yester