web-dev-qa-db-ja.com

OpenCVで画像を保存する

OpenCVは初めてで、画像をキャプチャしてからファイルに保存しようとしています。参照用のコードを以下に掲載しています。

Jpgファイルは保存されていますが、黒です。

// 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

すべての機能が成功しています。上記のコードをXPとVistaの両方で試してみました-結果は両方で黒い画像です。

26
Sujay Ghosh

C++を使用する場合は、C++インターフェイスを使用が最適です。

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
21

私の経験では、OpenCVはSaveImageに8ビットとは異なるビット深度の行列が与えられたときに黒い画像を書き込みます。実際、これは一種の文書化されています:

この機能を使用して保存できるのは、8ビットのシングルチャンネルまたは3チャンネル(「BGR」チャンネル順)の画像のみです。形式、深度、またはチャネルの順序が異なる場合は、cvCvtScaleおよびcvCvtColorを使用して変換してから保存するか、ユニバーサルcvSaveを使用して画像をXMLまたはYAML形式に保存します。

あなたの場合、最初にどんな種類の画像がキャプチャされるかを調査し、キャプチャプロパティを変更します(CV_CAP_PROP_CONVERT_RGBが重要であると思われます)、または後で手動で変換します。

これは、OpenCVで8ビット表現に変換する方法の例です。 ccは、CV_32FC1型の元のマトリックスです。cc8uは、実際に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)

(申し訳ありませんが、これはPythonコードですが、C/C++に簡単に変換できるはずです))

5
sastanin

CvQueryFrame()の最初の呼び出しで空の画像が返される場合があります。試してください:

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

それでもうまくいかない場合は、キャプチャデバイスを自動的に選択してください。

CvCapture *pCapturedImage = cvCreateCameraCapture(-1);

または、n = 1,2,3 ...である他のキャプチャデバイスを選択することもできます。

CvCapture *pCapturedImage = cvCreateCameraCapture(n);

PS:また、キャプチャした画像が変数名を見て誤解していると思います。変数pCapturedImageは、キャプチャではなく、イメージです。キャプチャから画像をいつでも「読み取る」ことができます。

5
nimcap

これがあまりにも明白な場合は申し訳ありません。つまり、WebカメラがOpenCVによって適切に表示および検出されていることを確認します。キャプチャしたフレームを「highGui」ウィンドウにリダイレクトすると、画像が表示されますか?たとえば次のように:

 frame = cvQueryFrame( capture );
 cvNamedWindow( "myWindow", CV_WINDOW_AUTOSIZE );
 cvShowImage( "myWindow", frame );
3
david h

私は問題を知っています! 「test.jpg」の後にドットを置くだけです!

cvSaveImage( "test.jpg"。、pSaveImg);

私は間違っているかもしれませんが、良くないと思います!

3
lf.

Microsoft WebCamでも同様の問題がありました。 Matlabの画像取得ツールボックスを見ると、サポートされている最大解像度は640 * 480であることがわかりました。

OpenCVのコードを変更して追加しました

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

次にサポートされる解像度であり変更されたcvQueryFrame関数の前に、イメージを保存する前にいくつかの初期フレームをスキップし、最終的に機能させました。

作業コードを共有しています

#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;
}

私の提案:

  1. 最大解像度でフレームを取得しない
  2. 正しいカメラ初期化のためにいくつかのフレームをスキップする
2

Windows Vistaでも同じ問題が発生しました。cvQueryFrameの前にこのコードを追加しました。

cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 720);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);
1
jmp4281

次のコードを使用して画像をキャプチャします。

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

私はこれが確実に機能することを知っています

1
Yogi

SayntLewisは正しい。 cvCaptureFromCAMでカメラをアクティブにしたとき、自動ホワイトバランスはまだ調整されていないため(遅いプロセスです)、最初のフレームでほとんどが白またはほとんどが黒になります(カメラと雷条件によって異なります)。シーンの稲妻が突然変化した場合にも同じことが起こります。カメラを開いてしばらく待ってから、バッファをフラッシュすれば準備完了です。

1
Vitor

OpenCVの健全性チェックを実行することをお勧めします

Opencvのbinディレクトリにある一連の小さな実行可能ファイル。

カメラが正常かどうかを確認します

1
Eric

古い投稿を掲載してすみませんが、このスレッドに出くわした人に別の回答を提供したかったのです。

同じ問題がありました。私が何をしたとしても、画像は完全な黒のように見えました。 cvQueryFrameを連続して複数回呼び出してみましたが、5回以上行ったときに画像が表示されることがわかりました。そこで、呼び出しを1つずつ削除して、「ブレークポイント」がどこにあるのかを確認し始めました。私が見つけたのは、各コールを削除すると画像がどんどん暗くなるということでした。呼び出しを1回行うだけで、ほぼ完全に黒の画像が提供されましたが、よく見ると、自分の画像を確認できました。

私は理論をテストするために10回連続して呼び出しを試みましたが、薄暗い部屋にいることを考えると、非常に明るい画像が与えられました。うまくいけば、これはあなたが遭遇したのと同じ問題でした。

イメージングについてはあまり知りませんが、cvQueryFrameを連続して複数回呼び出すと、カメラの露出時間が長くなるようです。これは間違いなく問題を解決しますが、最もエレガントな解決策とは思えません。露出を増やすパラメータ、または画像を明るくする他のパラメータを見つけることができるかどうかを確認します。

幸運を!

1
SayntLewis

OSXでは、cvSaveImageへのフルパスを指定した場合にのみ、ビデオフレームと静止画像の保存が機能しました。

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

単純にカメラは最初のフレームで初期化されないと思います。 10フレーム後に画像を保存してください。

0
chronos

私の経験から、使用時にキャプチャされる最初のいくつかのフレーム:

frame = cvQueryFrame( capture );

空白になる傾向があります。しばらく(約3秒)待ってから、画像をキャプチャしてみてください。

0
Nexus

うまくいけば、これはあなたのウェブカメラから画像を保存します

#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); 
}
0
Haris Hussain