2008年6月21日 星期六

GUI介面的製作-主控台介面的關閉

當你在做GUI介面的時候,會有黑底白字的命令及提示字元出現真的很討厭,明明已經是視窗介面了,為什麼還需要有黑框跑出來,這個問題在OpenCV的程式裡都是這樣執行的,也許久而久之就習慣了,不過,OpenCV還是可以做得到純GUI介面,需要用到的是"wincon.h"(Windows Console)主控台控制介面的函式庫,它包在"windows.h"裡,而實際上"highgui.h"就有包含"windows.h"的函式庫,直接用"highgui.h"就好了,而要關閉黑底白字的主控台介面其實很簡單,就只要用到FreeConsole()這個函式就好了,但是,主控台介面還是必要的,因為OpenCV視窗介面少了很多視窗介面該有的功能,如Label,Button,Eidt,Memo等文字輸入/顯示的設計,如果真的需要看到文字顯示資訊,或是輸入資料,主控台的存在是不可或缺的.當關閉主控台介面時,如果說遇到要暫時輸入文字資訊則在用AllocConsole()再度開啟主控台吧.

Webcam關閉主控台程式
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <windows.h>


int main()
{
    FreeConsole();

    CvCapture *capture;
    IplImage *frame;

    capture =cvCaptureFromCAM(0) ;

    cvNamedWindow("Webcam",0);
    while(true)
    {
        frame = cvQueryFrame(capture);

        cvShowImage("Webcam",frame);

        if(cvWaitKey(10)>=0)
        {
            break;
        }

    }
    cvReleaseCapture(&capture);
    cvDestroyWindow("Webcam");

}
執行結果:


這裡實際上存在一個很嚴重的問題,當把主控台介面關閉的時候,雖然只會出現圖形介面,但是,主控台的操控是在背景作業的,而開啟的視窗介面是一個執行緒,想了解執行緒是什麼則要去看作業系統原理等相關書籍,所以在這邊,如果是用cvWaitKey()的方法按鍵盤任意鍵結束視窗介面是不會有什麼問題的,可是如果是按GUI介面上右上角的關閉視窗,就會造成GUI介面這個執行緒被關閉,而實際上,背景作業的行程(process)仍在繼續執行,如果說是用圖片檔實作是沒什麼太大的問題,可是如果是用視訊播放程式的話,即使把GUI介面關閉,但是它裝置還是在繼續播放的.它仍然在跑while迴圈,仍然在不停的讀圖片,而這時的cvWaitKey()也失去作用了,因為cvWaitKey()是等待GUI介面上鍵盤事件的發生,而GUI介面這個執行緒被關閉了,就會變成只會卡記憶體(約8MB以上),每秒不斷造成分頁錯誤的程式了.

產生問題:每秒產生988個分頁錯誤(分頁錯誤差異),卡死記憶體8700KB(8MB)


要解決這樣的問題就要多加一個判斷,當視窗介面的執行緒被關閉的時候就要順便把行程也關閉,程式碼如下

Webcam關閉主控台程式2
#include <cv.h>
#include <highgui.h>
#include <stdio.h>
#include <windows.h>

int main()
{
    FreeConsole();

    CvCapture *capture;
    IplImage *frame;

    capture =cvCaptureFromCAM(0) ;

    cvNamedWindow("Webcam",0);
    while(true)
    {
        frame = cvQueryFrame(capture);

        cvShowImage("Webcam",frame);

        if(cvWaitKey(10)>=0)
        {
            break;
        }
        if(!cvGetWindowHandle("Webcam"))
        {
            break;
        }
    }
    cvReleaseCapture(&capture);
    cvDestroyWindow("Webcam");

}

這邊的判斷就只是多做了一個偵測"Webcam"這個視窗的HWND是否存在,如果不存在的話就跳出while迴圈,而程式才會繼續跳出while的下一步釋放記憶體並關閉這個程式的行程.

FreeConsole()
主控台介面背景作業

AllocConsole()
重新開啟主控台介面



2 意見:

kk7575 提到...

能請問我照你的程式碼在vs2008上執行
會出現
1>webcom.obj : error LNK2019: 無法解析的外部符號 _cvDestroyWindow 在函式 _main 中被參考
1>webcom.obj : error LNK2019: 無法解析的外部符號 _cvReleaseCapture 在函式 _main 中被參考
1>webcom.obj : error LNK2019: 無法解析的外部符號 _cvWaitKey 在函式 _main 中被參考
1>webcom.obj : error LNK2019: 無法解析的外部符號 _cvShowImage 在函式 _main 中被參考
1>webcom.obj : error LNK2019: 無法解析的外部符號 _cvQueryFrame 在函式 _main 中被參考
1>webcom.obj : error LNK2019: 無法解析的外部符號 _cvNamedWindow 在函式 _main 中被參考
1>webcom.obj : error LNK2019: 無法解析的外部符號 _cvCreateCameraCapture 在函式 _main 中被參考
1>D:\Yu\projects\webcom\Debug\webcom.exe : fatal error LNK1120: 7 個無法解析的外部符號

yester 提到...

在方案總管->專案->屬性->組態屬性->連結器->輸入->其他相依性那邊加上highgui200.lib

Copyright 2008-2009,yester