2008年6月20日 星期五

GUI介面的製作-轉檔程式的實作

圖片檔案格式的轉換其實很簡單,應為所有轉換格式的演算法都包在cvLoadImage(),cvSaveImage()裡啦,對OpenCV而言,可以不用去知道如何去實作它的圖檔格式而做到直接開啟的功能,而他讀到的檔案甚至連它的相關資訊全都包在IplImage資料結構裡,以下是簡單的轉檔程式實作

圖檔格式的轉換
#include <cv.h>
#include <highgui.h>
#include <stdio.h>

int main()
{
    IplImage *Image1;
    char FileName[10],ConvertFormatAndName[10];

    printf("檔案名稱\n>");
    scanf("%s",&FileName);
    printf("轉檔名稱(jpg,bmp,tif,png,ppm,)\n>");
    scanf("%s",&ConvertFormatAndName);

    if((Image1=cvLoadImage(FileName,-1))!=0)
    {
        cvSaveImage(ConvertFormatAndName,Image1);
    }

}
執行結果:
(1)ghyll.jpg轉檔前

(2)執行轉檔程式

(3)轉檔後


非常的簡單又簡短吧!實際上也只用到cvLoadImage()跟cvSaveImage()的存檔讀檔的動作,比較複雜的一層已經被包在cvLoadImage()跟cvSaveImage()的副程式裡面了,當然,只用到單純檔案轉換根本不夠看,因為有很多應用軟體都可以做到檔案轉換的功能,但假使,今天有好幾千張的jpg圖檔要轉換成bmp圖檔,光是用軟體慢慢一張張開啟轉換就會累個半死,而有了這些source code就可以做更多更強大的應用.

將目錄下的所有圖檔做轉換
#include <stdio.h>
#include <stdlib.h>
#include <cv.h>
#include <highgui.h>
#include <string.h>
#include <dirent.h>

DIR *DIR1;
struct dirent *Entry1;
char *StrPointer;
char picFormat[4];

IplImage *Image1;
int main()
{
    printf("====轉檔程式====\n");
    printf("這是將跟執行檔同目錄底下的所有圖片包含\nbmp,dib\njpg,jpge,jpe,jp2\n");
    printf("exr\npng\ntif,tiff\npbm,pgm,ppm\nras,sr\n副檔名轉成目標檔案格式的程式\n");
    printf("\n\n請輸入要轉檔副檔名名稱\n");
    printf("(bmp,dib,jpg,jpge,jpe,jp2,exr,png,tif,tiff,pbm,pgm,ppm,ras,sr)\n\n> ");
    scanf(" %s",&picFormat);

    DIR1=opendir(".");
    while(Entry1=readdir(DIR1))
    {

        if((StrPointer=strstr(Entry1->d_name,".bmp"))||
           (StrPointer=strstr(Entry1->d_name,".dib"))||
           (StrPointer=strstr(Entry1->d_name,".jpg"))||
           (StrPointer=strstr(Entry1->d_name,".jpge"))||
           (StrPointer=strstr(Entry1->d_name,".jpe"))||
           (StrPointer=strstr(Entry1->d_name,".jp2"))||
           (StrPointer=strstr(Entry1->d_name,".exr"))||
           (StrPointer=strstr(Entry1->d_name,".png"))||
           (StrPointer=strstr(Entry1->d_name,".tif"))||
           (StrPointer=strstr(Entry1->d_name,".tiff"))||
           (StrPointer=strstr(Entry1->d_name,".pbm"))||
           (StrPointer=strstr(Entry1->d_name,".pgm"))||
           (StrPointer=strstr(Entry1->d_name,".ppm"))||
           (StrPointer=strstr(Entry1->d_name,".ras"))||
           (StrPointer=strstr(Entry1->d_name,".sr")))
        {

            Image1=cvLoadImage(Entry1->d_name,-1);

            strncpy(StrPointer+1,picFormat,3);

            cvSaveImage(Entry1->d_name,Image1);

            printf("%s\n",Entry1->d_name);
        }

    }

    system("pause");
}

執行結果:
(1)轉檔前

(2)選定副檔名

(3)執行列表

(4)轉檔後


這是將所有目錄底下的圖片,全部的圖檔格式轉成目標想要的圖檔,數量很大的時候跑程式會方便又省時,或是遇到一堆圖檔都開不起來的時候,也可以用這種方法將之轉換.
程式一開始用了"dirent.h"的函式庫,以及他函式庫底下DIR跟dirent(directory entry)資料結構,接著就是開啟dir目錄的列表,這邊用"."代表的是執行檔下的目錄位置,也就是相對位置,也可以用"c:\\xxx\"等路徑,也就是目錄底下的絕對位置,這邊開啟的結果會放在DIR資料結構內,再用readdir()檢視列表,將readdir()的結果放在dirent的資料結構內,有寫過資料庫相關程式設計的話,用法其實很相似的.它會逐次將目錄下的東西列出來,這邊擷取副檔名為跟圖形相關的檔案(bmp,jpg,png...)來做存取的動作,再用前面的scanf()輸入的副檔名名稱來做轉檔.

cvLoadImage()
被放在"highgui.h"裡,可以讀取不同圖檔格式,也可以藉由參數去轉全彩或灰階.
IplImage* cvLoadImage("讀取圖檔名稱",參數);

cvSaveImage()
被放在"highgui.h"裡,可以儲存成不同圖檔格式.
cvSaveImage("儲存圖檔名稱",IplImage資料結構);



4 意見:

leo 提到...

compiler error.....無 dirent.h 檔案,

匿名 提到...

編譯器訊息
too few arguments to funtion 'cvSaveImage'

後來在cvSaveImage的最後多補一個0
cvSaveImage(ConvertFormatAndName,Image1,0)

才編譯通過(Dev-C++4.9.9.2)

匿名 提到...

Run-Time Check Failure #2 - Stack around the variable 'ConvertFormatAndName' was corrupted.

轉完檔之後出現這個警示訊息 該怎麼辦

匿名 提到...

你好~想請問一下有辦法利用cvSaveImage把Camera視頻即儲存成.jpg檔嗎?

Copyright 2008-2009,yester