2009-05-12 16 views
23

Jestem nowym użytkownikiem OpenCV i próbuję przechwycić obraz, a następnie zapisać go w pliku. Poniżej zamieszczam kod referencyjny.Zapisywanie obrazu w OpenCV

Plik JPG jest zapisywany, ale jest czarny.

// Capture the Image from the webcam 
CvCapture *pCapturedImage = cvCreateCameraCapture(0); 

// Get the frame 
IplImage *pSaveImg = cvQueryFrame(pCapturedImage); 

// Save the frame into a file 
cvSaveImage("test.jpg". ,pSaveImg); // A JPG FILE IS BEING SAVED 
            // OF 6KB , BUT IT IS BLACK 

Wszystkie funkcje są skuteczne. Próbowałem powyższego kodu w obu XP i Vista - wynik jest czarny obraz na obu. Daj mi znać, czego mi brakuje.

Odpowiedz

5

Czasami pierwsze wywołanie cvQueryFrame() zwraca pusty obraz. Spróbuj:

IplImage *pSaveImg = cvQueryFrame(pCapturedImage); 
pSaveImg = cvQueryFrame(pCapturedImage); 

Jeśli to nie zadziała, spróbuj wybrać urządzenie przechwytywania się automatycznie:

CvCapture *pCapturedImage = cvCreateCameraCapture(-1); 

Albo można spróbować wybrać inne urządzenia do przechwytywania, gdzie n = 1,2,3 ...

CvCapture *pCapturedImage = cvCreateCameraCapture(n); 

PS: Wierzę również, że istnieje nieporozumienie dotyczące przechwyconego obrazu patrząc na nazwę zmiennej. Zmienna pCapturedImage nie jest obrazem, jest przechwytywaniem. Zawsze możesz "odczytać" obraz z przechwytywania.

+0

Nadal dostaję czarny obraz. Próbowałem tego nawet przez chwilę; który pęka po naciśnięciu "q". Używam również cvVideoWriter, aby zapisać przechwycone klatki do pliku wideo (avi), nadal otrzymuję plik z czarną zawartością. Czy muszę zainstalować kodeki, aby OpenCV działał poprawnie. Dzięki Sujay I pojawia się czarny jpg, blac –

+0

Nie jestem pewien, będę w stanie dalej pomóc. – nimcap

1

używam następujący kod do robienia zdjęć:

CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY); 
if(!capture) error((char*)"No Capture"); 
IplImage *img=cvQueryFrame(capture); 

wiem, że to działa na pewno

3

przepraszam, jeśli to zbyt oczywiste. Czy jesteś pewien, że kamera internetowa jest odpowiednio widoczna i wykrywana przez OpenCV innymi słowy, czy otrzymujesz obraz po przekierowaniu przechwyconej klatki do okna "highGui"? Na przykład tak:

frame = cvQueryFrame(capture); 
cvNamedWindow("myWindow", CV_WINDOW_AUTOSIZE); 
cvShowImage("myWindow", frame); 
+0

Ten kod daje mi również czarny obraz. Czy muszę zainstalować kodeki, czy są jakieś zależności? Moja kamera internetowa jest uruchomiona, ale jest czarny obraz –

0

Z mojego doświadczenia pierwszych kilka klatek, które są zrobione przy użyciu:

frame = cvQueryFrame(capture);

wydają się być puste. Możesz odczekać chwilę (około 3 sekundy), a następnie spróbować zrobić zdjęcie.

1

Proponuję uruchomić OpenCV testow

Jest to seria małych plików wykonywalnych znajdujących się w katalogu bin OpenCV.

To będzie sprawdzić, czy kamera jest ok

+0

Dzięki za informacje. Sprawdzę to. Ale myślę, że mój aparat jest w porządku, ponieważ przy użyciu RoboRealm, narzędzia robotyki, widzę mój obraz i piksel. Używam również kamery internetowej do wideokonferencji, a ludzie mnie widzą. –

+0

Próbowałem uruchomić opencv na moim netbooku, kamera zwykle działa dobrze, ale z jakiegoś powodu nie przechodzi testów poprawności. Nie mogę tego zrobić, ani – Eric

3

Znam ten problem! Po prostu umieść kropkę po "test.jpg"!

cvSaveImage ("test.jpg" pSaveImg.);

Mogę się mylić, ale myślę, że nie jest dobrze!

0

Myślę, po prostu aparat nie zainicjować w pierwszej klatce. Spróbuj zapisać obraz po 10 klatkach.

1

Miałem ten sam problem w systemie Windows Vista, po prostu dodaje ten kod przed cvQueryFrame:

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 720); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480); 
5

Z mojego doświadczenia OpenCV pisze czarny obraz podczas SaveImage jest daną matrycę z głębi bitowej innej niż 8 bitów. W rzeczywistości jest to rodzaj udokumentowane:

tylko 8-bitowy jednokanałowym albo 3, kanał (z „BGR” zamów kanał) obrazów może być zapisywane za pomocą tej funkcji. Jeśli format , głębokość lub kolejność kanałów jest inny, użyj cvCvtScale i cvCvtColor aby przekształcić go przed oszczędności lub użyj uniwersalny cvSave do zapisać obraz w formacie XML lub YAML.

W twoim przypadku może najpierw zbadać, jakiego rodzaju obraz jest rejestrowany, właściwości wychwytywania zmian (przypuszczam CV_CAP_PROP_CONVERT_RGB może być ważne) lub przekształcić go ręcznie później.

To jest przykład konwertowania na 8-bitową reprezentację za pomocą OpenCV. cc tutaj jest oryginalna matryca typu CV_32FC1, cc8u jest jego skalowany wersja, która jest faktycznie napisane przez SaveImage:

# I want to save cc here 
cc8u = CreateMat(cc.rows, cc.cols, CV_8U) 
ccmin,ccmax,minij,maxij = MinMaxLoc(cc) 
ccscale, ccshift = 255.0/(ccmax-ccmin), -ccmin 
CvtScale(cc, cc8u, ccscale, ccshift) 
SaveImage("cc.png", cc8u) 

(przepraszam, to jest kod Python, ale to powinno być łatwe do przetłumaczenia go do C/C++)

1

Przepraszam, że wychwalam stary post, ale chciałem udzielić innej odpowiedzi każdemu, kto napotka ten wątek.

Miałem ten sam problem. Bez względu na to, co zrobiłem, obraz wyglądał tak, jakby był całkowicie czarny. Próbowałem wykonywać wiele kolejnych wywołań do cvQueryFrame i zauważyłem, że gdy zrobiłem 5 lub więcej, mogłem zobaczyć obraz. Zacząłem więc usuwać połączenia jeden po drugim, aby zobaczyć, gdzie jest "punkt przełomowy". W końcu odkryłem, że obraz staje się coraz ciemniejszy, gdy usuwam każde połączenie. Wykonanie tylko jednego połączenia dostarczyło obraz prawie całkowicie czarny, ale gdybym spojrzał bardzo uważnie, mogłem rozpoznać mój wizerunek.

Próbowałem 10 kolejnych połączeń, aby przetestować moją teorię, i na pewno dano mi bardzo jasny obraz, biorąc pod uwagę, że jestem w słabo oświetlonym pokoju. Mam nadzieję, że był to ten sam problem, z którym się zetknąłeś.

Nie wiem zbyt wiele na temat obrazowania, ale wygląda na to, że wiele kolejnych wywołań do cvQueryFrame wydłuża czas ekspozycji kamery. To zdecydowanie rozwiązuje problem, choć nie wydaje się najbardziej eleganckim rozwiązaniem. Zobaczę, czy uda mi się znaleźć parametr, który zwiększy ekspozycję, czy może jakiś inny parametr, który rozjaśni moje obrazy.

Powodzenia!

+0

Dzięki Sayn, kiedyś spróbuję. –

+0

Nie chodzi o ekspozycję; to Twój aparat automatycznie dostosowuje się do aktualnego oświetlenia w pomieszczeniu. Ponieważ nie ma zbyt wiele światła, oprogramowanie aparatu kompensuje, ale nie jest natychmiastowe. –

0

na OSX, zapisywanie klatek wideo i zdjęć pracował tylko dla mnie, kiedy dałem pełną ścieżkę do cvSaveImage:

cvSaveImage("/Users/nicc/image.jpg",img); 
1

SayntLewis ma rację. Po włączeniu kamery za pomocą cvCaptureFromCAM, automatyczny balans bieli nie jest jeszcze wyregulowany (proces jest powolny), więc na pierwszych klatkach może pojawić się przeważnie biały lub przeważnie czarny (w zależności od aparatu i warunków oświetleniowych). To samo dzieje się w przypadku nagłej zmiany błyskawicy sceny. Po prostu poczekaj chwilę po otwarciu aparatu, przepłucz bufor i jesteś gotowy do pracy.

17

Jeśli używasz C++, to najlepiej używać C++ interfejsu:

using namespace cv; 
// Capture the Image from the webcam 
VideoCapture cap(0); 

// Get the frame 
Mat save_img; cap >> save_img; 

if(save_img.empty()) 
{ 
    std::cerr << "Something is wrong with the webcam, could not get frame." << std::endl; 
} 
// Save the frame into a file 
imwrite("test.jpg", save_img); // A JPG FILE IS BEING SAVED 
+0

Podążałem za tutorialem OpenCV, czy to coś innego. –

2

miałem podobny problem z moim Microsoft WebCam. Zajrzałem do zestawu narzędzi do pobierania obrazów w programie Matlab i okazało się, że maksymalna obsługiwana rozdzielczość to 640 * 480.

Właśnie zmienił kod w OpenCV i dodał

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 352); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 288); 

przed funkcją cvQueryFrame który był kolejnym obsługiwanej rozdzielczości i zmienił pomijane pewne wstępne ramki przed zapisaniem obrazu i wreszcie to działa.

dzielę mój Kodeks pracy

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



using namespace cv; 
using namespace std; 

int main() 
{ 
CvCapture* capture = cvCaptureFromCAM(CV_CAP_ANY); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 352); 
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 288) 


// Get one frame 
IplImage* frame; 

for (int i = 0; i < 25; i++) 
{ 
frame = cvQueryFrame(capture); 
} 


printf("Image captured \n"); 
//IplImage* RGB_frame = frame; 
//cvCvtColor(frame,RGB_frame,CV_YCrCb2BGR); 
//cvWaitKey(1000); 
cvSaveImage("test.jpg" ,frame); 
//cvSaveImage("cam.jpg" ,RGB_frame); 

printf("Image Saved \n"); 

//cvWaitKey(10); 

// Release the capture device housekeeping 
cvReleaseCapture(&capture); 
//cvDestroyWindow("mywindow"); 
return 0; 
} 

Moje propozycje:

  1. Dont grab ramka z maksymalną rozdzielczością
  2. pominąć niektóre klatki dla prawidłowego aparatu inicjalizacji
0

Mam nadzieję, że spowoduje to zapisanie obrazów z kamery internetowej:

#include <opencv2/core/core.hpp> 
#include <opencv2/highgui/highgui.hpp> 
#include <opencv2/imgproc/imgproc.hpp> 
#include <iostream> 

using namespace std; 
using namespace cv; 

int main() 
{ 
    VideoCapture cap(0); 

    Mat save_img; 

    cap >> save_img; 

    char Esc = 0; 

    while (Esc != 27 && cap.isOpened()) {   
    bool Frame = cap.read(save_img);   
    if (!Frame || save_img.empty()) {  
     cout << "error: frame not read from webcam\n";  
     break;            
    } 
    namedWindow("save_img", CV_WINDOW_NORMAL); 
    imshow("imgOriginal", save_img);    
    Esc = waitKey(1); 
} 
imwrite("test.jpg",save_img); 
}