2012-01-12 2 views
17

이미지 데이터베이스를 통해 검색하는 프로젝트에서하고 있으며 일부 쿼리 - 5 데이터베이스 이미지에 대한 결과를 시각적으로 표시하고 싶습니다. 모든 이미지를 메모리에 보관하지 않으므로 이미지를 표시하기 위해 먼저 이미지를로드해야합니다.OpenCV - 이미지 디스플레이 창 닫기

IplImage *img; 

for (int i=0; i < 5; ++i){ 
    img = cvLoadImage(images[i].name.c_str(),1); 
    cvShowImage(("Match" + images[i].name).c_str(), img); 
    cvWaitKey(0); 
    cvDestroyWindow(("Match" + images[i].name).c_str()); 
    // sleep(1); 
    cvReleaseImage(&img); 
} 

여기에 사용 images 배열로하지 않습니다 이러한 목적을 위해 OpenCV를 사용 C++에 여기

for image 1..5 
    load images 
    display image in a window 
    wait for any keypress 
    close the window 

내 코드의 조각이다 :

나는 의사의 마음에 뭔가를 간단했다 그러한 것들이 내 코드에 존재하지만, 질문을 위해서, 그것은 name 회원 인 경우 현재 프로그램 실행 포인트와 관련된 이미지의 파일 이름을 포함합니다. 프로젝트에서 이미지 이름을 약간 다르게 저장합니다.

거의 작품 위의 코드 : 나는 OK 4/5 이미지를 반복 할 수 있지만, 마지막 이미지가 표시되고 키를 누를 때, 이미지가 회색 간다 내가 나머지를 충돌 withouth 이미지 창을 닫을 수 없습니다 내 신청서의

내 첫 번째 아이디어는 컴파일 시간 최적화 때문에 cvReleaseImagecvDestroyWindow이 완료되기 전에 이미지를 해제하고 어떻게 든 멈추게한다는 것입니다. 그러나, 나는 약간의 대기 시간 (그러므로 내 코드의 sleep(1) 행을 주석으로 처리했다)을 추가하려고 시도했지만 도움이되지 않았다.

내 콘솔 응용 프로그램에서이 디스플레이 기능을 호출하고 이미지가 정지되면 컨트롤이 내 응용 프로그램으로 돌아가고 계속 사용할 수 있지만 이미지 창은 여전히 ​​백그라운드에서 고정되어 있습니다.

해결 방법에 대한 의견을 보내주십시오.

나는 여전히 아이디어를 질문을하기 때문에 정기적으로 컴퓨터 비전과 OpenCV의 다루는 사람들에게 이야기하지 않고, 한

편집 할 수 있습니다.

나는 또한 stackoverflow question과 유사한 것을 발견했으나 여전히 받아 들여지지 않은 대답이 있습니다. Google은 결과와 비슷한 질문을하지만 대답은 제공하지 않습니다.

시도해 봐야 할 아이디어 (완벽한 해결책이 아닐지라도)는 대단히 감사하겠습니다.

+0

이미지 배열에 대해 알려주시겠습니까? 생성 및 할당 코드를 게시 할 수 있습니까? BTW 당신은 ​​이것을 C++로 태그를 붙였습니다. 그렇다면 왜 이전 C 스타일의 opencv를 사용하고 있습니까? – Boaz

+0

OpenCv의 C 스타일은 내 코드에서 OpenCV를 사용하는 C 라이브러리를 사용해야했기 때문에 데이터 중 일부는 C 스타일 OpenCV 데이터 구조에 있습니다. 실제로이 코드는 훨씬 더 큰 코드 조각으로, 이미지의 이름에 훨씬 다른 방식으로 액세스합니다. 질문을 위해서, images 배열에는 .name 멤버의 그림에 대한 파일 경로가 포함되어 있습니다. (질문을 업데이트합니다) – penelope

+0

'cvDestroyAllWindows()'를 사용해 보셨습니까? 그렇다면 작동하지 않으며 어딘가에 (어쩌면 위와 같지 않음) 또는 OpenCv에서 이상한 버그가있는 것입니다. 그것이 작동하면 어딘가에 간단한 버그가 있습니다. – Florian

답변

15

아래 응용 프로그램은 당신이 질문에 명시된 정확히 무엇을 : 그것은 명령을 통해 7 개 이미지를로드 한 줄씩 차례로 표시하고 표시 할 각 이미지에 대해 새 창을 만듭니다.

Linux의 OpenCV 2.3.1에서 완벽하게 작동합니다.

#include <cv.h> 
#include <highgui.h> 

#define NUM_IMGS 7 

int main(int argc, char* argv[]) 
{ 
    if (argc < 8) 
    { 
     printf("Usage: %s <img1> <img2> <img3> <img4> <img5> <img6> <img7>\n", argv[0]); 
     return -1; 
    } 

    // Array to store pointers for the images 
    IplImage* images[NUM_IMGS] = { 0 }; 

    for (int i = 0; i < NUM_IMGS; i++) 
    { 
     // load image 
     images[i] = cvLoadImage(argv[i+1], CV_LOAD_IMAGE_UNCHANGED); 
     if (!images[i]) 
     { 
      printf("!!! failed to load: %s\n", argv[i+1]); 
      continue; 
     } 

     // display image in a window 
     cvNamedWindow(argv[i+1], CV_WINDOW_AUTOSIZE); // creating a new window each time 
     cvShowImage(argv[i+1], images[i]); 

     // wait for keypress 
     cvWaitKey(0); 

     // close the window 
     cvDestroyWindow(argv[i+1]); 
     cvReleaseImage(&images[i]); 
    } 

    return 0; 
} 
-2

에 한번 각 프레임에 윈도우를 파괴 할 필요가 없습니다

cvDestroyWindow("Match"); 
// sleep(1); 
cvReleaseImage(&img); // outside the for loop 
+0

왜? 그게 어떻게 도움이 될까요? 새 이미지를로드하기 전에 이전 이미지를 놓지 않으면 모든 이미지가 실제로 메모리에 남아 있지 않습니까? – penelope

2

를 사용하여, 당신은 단순히 동일한 창 이름으로 cvShowImage()를 호출 할 수 있으며 현재 이미지를 대체합니다.

종료 할 때 destroy window를 호출하면됩니다. 시작할 때 cvCreateWindow()를 사용하여 창을 만들 수 있지만 첫 번째 showWindow() 호출시 자동으로 만들어집니다.

+0

안녕하세요, 대답은 thnx이지만 각 창마다 실제로 다른 이름이 있습니다. 문제는 윈도우를 표시하는 것이 아니라,'cvDestroyWindow'가 윈도우를 닫지 않는다는 것입니다. 정확하게 말하면, 마지막 윈도우는 열려 있습니다. – penelope

5

cvDestroyWindow() 보통 만 시작하면 창문 파괴가 꽤 복잡한 절차입니다. 이 절차에서는 윈도우 시스템과 응용 프로그램간에 약간의 상호 작용 (이벤트 교환)이 필요합니다. 이 절차가 끝날 때까지는 창을 완전히 파괴 할 수 없습니다.이것이 응용 프로그램이 GUI와 관련이없는 무언가를 수행하는 동안 부분적으로 파괴 된 창을 보는 이유입니다.

이벤트 교환은 시스템 종속적 인 방식으로 수행 될 수 있습니다. Windows에서 이것은 직접 또는 간접적으로 GetMessage 또는 MsgWaitFor* 함수를 호출하고 결과를 처리하는 것을 의미합니다. Unix의 경우 이는 직접 또는 간접적으로 XNextEvent을 호출하고 그 결과를 처리하는 것을 의미합니다.

OpenCV는이 이벤트 교환을 시스템 독립적 인 방식으로 수행 할 수있게합니다. 이를 위해 문서화 된 두 가지 방법이 있습니다. 첫 번째 이미지는 cvWaitKey()입니다 (마지막 이미지를 닫은 후 cvWaitKey(1)로 전화하면됩니다). 두 번째는 프로그램 시작시 cvStartWindowThread()으로 전화해서 OpenCV가 자동으로 창을 업데이트 할 수있게하는 것입니다.

libcv2.1을 사용하는 Linux 상자에서이 방법 중 하나만 올바르게 작동했습니다 : cvStartWindowThread().


업데이트 (cvStartWindowThread와 코드는()) 테스트 목적으로

//gcc -std=c99 main.c -lcv -lcxcore -lhighgui 
#include <opencv/cv.h> 
#include <opencv/highgui.h> 
#include <stdio.h> 
#include <unistd.h> 

#define NUM_IMGS 2 

int main(int argc, char* argv[]) 
{ 
    if (argc < 2) 
    { 
     printf("Usage: %s <img1>\n", argv[0]); 
     return -1; 
    } 

    cvStartWindowThread(); 

    // Array to store pointers for the images 
    IplImage* images[NUM_IMGS] = { 0 }; 

    for (int i = 0; i < NUM_IMGS; i++) 
    { 
     // load image 
     images[i] = cvLoadImage(argv[i+1], CV_LOAD_IMAGE_UNCHANGED); 
     if (!images[i]) 
     { 
      printf("!!! failed to load: %s\n", argv[i+1]); 
      continue; 
     } 

     // display image in a window 
     cvNamedWindow(argv[i+1], CV_WINDOW_AUTOSIZE); // creating a new window each time 
     cvShowImage(argv[i+1], images[i]); 

     // wait for keypress 
     cvWaitKey(0); 

     // close the window 
     cvDestroyWindow(argv[i+1]); 
     cvReleaseImage(&images[i]); 
    } 

    // cvWaitKey(1); 
    sleep(10); 
    return 0; 
} 
+0

cvStartWindowThread() 사용 방법에 대한 코드 스 니펫을 보여 주실 수 있습니까? 난 당신이 제안한 첫 번째 솔루션 (창 파괴 후 cvWaitKey (1) 퍼팅) 같은 문제가 직면하고있어. 내 프로그램이 계속 실행되는 나머지 시간 동안 이미지가 표시되지 않은 상태에서 빈 창을 계속 엽니 다. 미리 알아 두십시오! – Matteo

+0

@Matteo, 코드 스 니펫을 추가했습니다. (한번 더 테스트 했는데도 올바르게 작동합니다.) 'cvWaitKey (1)'도 나에게 효과가 없었다. –

+0

Thks 많이, 정말 간단 해 보인다! 또 다른 질문 : 이미지를 표시하는 함수를 사용하면 전역 또는 로컬 범위에서 스레드를 만드는 것이 좋습니다? 이 함수를 여러 번 main에서 호출해야 할 수도 있습니다. – Matteo

0

다섯 번째 이미지가 올바르게로드되었는지 테스트 했습니까? 이건 어때?

for(...) 
{ 
    if(!img) 
     break; 

    // display it 
} 

발생하는 문제는 cvShowImage()에 대한 null 포인터처럼 들립니다.

1

코드에서 이미지를 표시하는 데 사용하는 창을 만드는 데는 cvNamedWindow()이라는 호출을 보지 않았습니다. cvShowImage() (karlphillip이 his answer에 표시됨) 전에 루프 중 하나에 해당 호출을 넣어야합니다.

루프 전에 명명 된 창을 만드는 경우 : 중복 된 이름을 가진 이미지가 있는지 확인 했습니까? 파괴 된 창에 이미지를 지정하지 않고 이미 파괴 된 창을 파괴하지 않도록하려면?

cvDestroyWindow()의 모든 통화를 생략하고 cvDestroyAllWindows() 번의 단일 통화를 사용하면 문제를 방지하는 데 도움이됩니까?

-1

openCV를 좋아하지만 테스트 쿼리의 검색 결과를 표시하는 유일한 방법은 아닙니다. 이미지 폴더의 루트에 C++ 코드의 html 파일을 작성하고 브라우저에서 열 수 있습니다.

웹 서버를 운영하는 경우 간단한 파일 목록을 작성하고 간단한 PHP 스크립트 또는 이와 유사한 방법으로 게시 할 수 있습니다. 이 방법의 장점에

<!DOCTYPE html> 
<html> 
    <head> 
    <style>img {display:block}</style> 
    <meta http-equiv="refresh" content="5"> 
    </head> 
    <body> 
    <img src="subfolderA/img1.png" /> 
    <img src="subfolderB/img2.png" /> 
    <img src="subfolderC/img3.png" /> 
    <img src="subfolderD/img4.png" /> 
    <img src="subfolderE/img5.png" /> 
    </body> 
</html> 

은 머리가없는 서버에서 실행할 수 있다는 것입니다 :

결과 HTML 코드가 같은 것이 될 것이다.

#include "cv.h" // include standard OpenCV headers, same as before 
#include "highgui.h" 
#include <stdio.h> 
#include <iostream> 

using namespace cv; // all the new API is put into "cv" namespace. Export its content 
using namespace std; 

void help(){ 
    cout << 
    "\nThis program shows how to use cv::Mat and IplImages converting back and forth.\n" 
    "Call:\n" 
    "./image img1.png img2.png img3.png img4.png img5.png\n" << endl; 
} 

int main(int argc, char** argv){ 
    help(); 
    namedWindow("Peephole", CV_WINDOW_AUTOSIZE); 
    int i=0; 
    while ((argc-1) > i){ 
    i++; 
    const char* imagename = argv[i]; 
    Ptr<IplImage> iplimg = cvLoadImage(imagename); // Ptr<T> is safe ref-conting pointer    class 
    if(iplimg.empty()){ 
     fprintf(stderr, "Can not load image %s\n", imagename); 
     return -1; 
    } 
    Mat img(iplimg); // cv::Mat replaces the CvMat and IplImage, but it's easy to convert 
    // between the old and the new data structures (by default, only the header 

    // is converted, while the data is shared) 

    if(!img.data) // check if the image has been loaded properly 
     return -1; 
    // it's easy to pass the new matrices to the functions that only work with IplImage or CvMat: 
    // step 1) - convert the headers, data will not be copied 
    // this is counterpart for cvNamedWindow 
    imshow("Peephole", img); 
    waitKey(); 
    } 
    destroyAllWindows(); 
    while (1) { 
    waitKey(10); 
    } 
    // all the memory will automatically be released by Vector<>, Mat and Ptr<> destructors. 
    return 0; 
} 
: openCV2.3에서 image.cpp 샘플을 기반으로 waitKey (특히 이벤트에 대한 노트) , destroyWindow이 코드 예 : opencv2.3에 대한 문서에서 이미지 디스플레이 창 모양을 닫는

0

모든 OpenCV 이미지 디스플레이 창을 닫으려면 을 사용하십시오. destroyAllWindows();