2008年6月14日 星期六

GUI介面的製作-Trackbar製作

上一篇,有關於圖形GUI相關的都已經介紹到,接著,就來加入Trackbar來做影像黑白圖(二值圖)的實作,在這裡,全彩圖要轉成黑白圖就必須要先轉成灰階圖,變成灰階圖之後就必須要設定一個門檻值才能轉成黑白圖,這邊則是用Trackbar來做動態門檻值的校調.

RainMan二值化製做(圖形,視窗,拉軸實作)
#include <stdio.h>
#include <stdlib.h>
#include <cv.h>
#include <highgui.h>


void * WindowHandle1;

char FileName[]="rain.jpg";
char TrackbarName[]="Threshold";

int TrackbarInitValue=180;
int TrackbarStopValue=255;

IplImage *Image1;
IplImage *Image2;
CvSize Image2Size;

void onTrackbar(int position);

int main()
{
    Image1 = cvLoadImage(FileName,CV_LOAD_IMAGE_GRAYSCALE);
    Image2Size = cvSize(Image1->width,Image1->height);
    Image2 = cvCreateImage(Image2Size,IPL_DEPTH_8U,1);

    cvNamedWindow("Show Image",0);
    cvMoveWindow("Show Image",0,0);
    cvResizeWindow("Show Image",300,400);

    cvCreateTrackbar(TrackbarName,"Show Image",&TrackbarInitValue,TrackbarStopValue,onTrackbar);
    printf("Now, Trackbar position is : %d\n",cvGetTrackbarPos(TrackbarName,"Show Image"));
    cvSetTrackbarPos(TrackbarName,"Show Image",177);

    WindowHandle1=cvGetWindowHandle("Show Image");
    printf("The Window Handle is : %d\n",WindowHandle1);
    printf("The Window Name is : %s\n",cvGetWindowName(WindowHandle1));

    cvShowImage("Show Image",Image1);

    cvWaitKey(0);

    cvDestroyWindow("Show Image");
    cvReleaseImage(&Image1);
    cvReleaseImage(&Image2);

}
void onTrackbar(int position)
{
    cvThreshold(Image1,Image2,position,255,CV_THRESH_BINARY);
    cvShowImage("Show Image",Image2);
}

執行結果:


跟前一篇程式碼比起來,這邊多創造了IplImage資料結構的Image2及一個CvSize資料結構的Image2Size,然後初始化Image2Size的大小為Image1的寬跟高,再用cvCreateImage()初始化Image2的圖形空間,這邊給Image2,8位元1個通道非負整數空間,也就是開了一個非負整數0~255的二維陣列,設立一個新的視窗,加上了cvCreateTrackbar()的函式,而使用cvCreateTrackbar()必須要給予Trackbar一個事件,事件的命名可以自由的取名字,這裡給它的事件名稱是void onTrackbar(int postion),預設Trackbar的位置在180,最大拉軸長度是255,用cvGetTrackbarPos()查看拉軸位置,再用cvSetTrackbarPos()重新定位拉軸位置為177,接著,在onTrackbar()中放入了cvThreshold()演算法函式,再用cvSohwImage()顯示二值化的結果.要注意的是,設定事件名稱的時候最好也符合命名規則,增加可讀性,在這邊OpenCV可寫的事件比一般GUI介面還少很多,如果有瞭解過GUI的事件(Event),大概就曉得為啥要這樣設計.
接著逐一介紹各副程式的功能,從"highgui.h"的開始:

cvCreateTrackbar()
創立一個Trackbar在目標視窗上,起始值從0開始,而Trackbar指標開始的位置跟Trackbar最大值要自己設定,再給他一個可控制的事件名稱,此Trackbar事件可自由命名,但是務必要讓他輸入一個int型別的變數如:void xxx(int position).
cvCreateTrackbar("Trackbar名稱","目標視窗名稱",指標開始數值,Trackbar最大值,Trackbar事件副程式名稱);

cvGetTrackbarPos()
檢視Trackbar的位置,需要給它Trackbar的名稱,目標視窗名稱.
int cvGetTrackbarPos("Trackbar名稱","目標視窗名稱");

cvSetTrackbarPos()
重新設定Trackbar的位置,需要給它Trackbar的名稱,目標視窗名稱.
cvGetTrackbarPos("Trackbar名稱","目標視窗名稱",新的拉軸位置數據);

接下來都非highgui.h的函式

cvSize()
初始化CvSize資料結構,放置長跟寬的整數值
CvSize cvSize(寬的數值,高的數值);

cvCreateImage()
初始化IplImage資料結構,創造一個空白的圖片基本的格式,格式內容可參考命名規則,再給他通道數(二維陣列的數目).
cvCreateImage(CvSize資料結構,IPL_DEPTH_系列參數,通道數);

onTrackbar()
自行定義名稱,主要是接收拉軸移動後的數值,此數值做為二值化的門檻值,通常拉軸移動的數值都是做為各個演算法的門檻值之用.
void onTrackbar(拉軸移動整數值);

cvThreshold()
此為演算法功能之ㄧ,跟門檻值相關的演算法蒐集的副程式,第一個引數為輸入圖,第二個引數為計算結果的圖,再來是門檻最大值,二值化門檻值參數.
cvThreshold(原始圖形IplImage資料結構,計算後結果IplImage資料結構,門檻值,最大門檻值數值,CV_THRESH_BINARY);



9 意見:

匿名 提到...

你好
我有一個疑問
在程式中並無回圈再檢查bar的位置改變
但程式執行時當你移動bar時
圖的結果卻會跟這改變
這倒底是什麼原因造成的

謝謝

wa114040@gmail.com 提到...

這是一種Win32 api事件佈署的寫法~

用到的是多執行緒(Multi-thread),可以藉由

cvCreateTrackbar(TrackbarName,"Show Image",&TrackbarInitValue,TrackbarStopValue,onTrackbar);
佈置(delegation)要觸發的事件

在交由這個process底下的Multi-thread來做處理~

匿名 提到...

您好,我照您的方法執行程式,但出來的圖卻是灰階的,而不是黑白的,這是為什麼呢?

阿蠻 提到...

會是灰階是因為中間多了一行cvShowImage("Show Image",Image1);
把它改成Image2,
或是註解掉就可以,
但是我移動Trackbar時windows會有記憶體錯誤的情況,不知道哪錯了(OpenCV 2.0)

MAY 提到...

您好
我執行時為何一拉BAR程式就當掉了呢?
謝謝教導

匿名 提到...

移動Trackbar出錯
後來發現是 Img1跟Img2 的channel要設一樣,img1 channel=3,所以img2 設1會錯
不知道是不是版本的問題我試用opencv 1.0

匿名 提到...

我也是....移動bar就出錯

匿名 提到...

2.0拉bar造成的錯誤 我用2.1就好了

阿彥 提到...

您好~請問門檻值177是怎麼定義出來的呢?

Copyright 2008-2009,yester