2012-01-10 39 views
0

私はopencvでaviを再生していて、ビデオで円検出をしようとしています。動画を再生するだけで壮大ですが、サークルを検出しようとすると動画が減速します。それが録画されたスピードの近くでビデオを再生させる方法はありますか?OpenCvでAVIを再生するのが遅い

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

int main(int argc, char** argv) 
{ 
    IplImage*img; 
    int key=0; 

CvCapture*capture = cvCaptureFromAVI("C:\\Users\\Nathan\\Desktop\\SnookVid.wmv"); 

if(!capture) return 1; 

int fps = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FPS); 

cvNamedWindow("circles", 0); 


while(key!='q'){ 
    img = cvQueryFrame(capture); 

    if(!img) break; 


IplImage* gray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1); 
//IplImage* hsv = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1); 
CvMemStorage* storage = cvCreateMemStorage(0); 

//covert to grayscale 
cvCvtColor(img, gray, CV_BGR2GRAY); 

// This is done so as to prevent a lot of false circles from being detected 
cvSmooth(gray, gray, CV_GAUSSIAN, 3, 5); 

IplImage* canny = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1); 
//IplImage* rgbcanny = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3); 
//cvCanny(gray, canny, 50, 70, 3); 

//detect circles 
CvSeq* circles = cvHoughCircles(gray, storage, CV_HOUGH_GRADIENT, 1, 27, 70, 40,0,0); 
//cvCvtColor(canny, rgbcanny, CV_GRAY2BGR); 
//cvCvtColor(img,hsv, CV_BGR2HSV); 
//draw all detected circles 
float* p; 
CvScalar s; 
int num_red = 22; 
for (int i = 0; i < circles->total; i++) 
{ 
    // round the floats to an int 
    p = (float*)cvGetSeqElem(circles, i); 
    cv::Point center(cvRound(p[0]), cvRound(p[1])); 
    int radius = cvRound(p[2]); 

    //uchar* ptr; 
    //ptr = cvPtr2D(img, center.y, center.x, NULL); 
    //printf("B: %d G: %d R: %d\n", ptr[0],ptr[1],ptr[2]); 


    s = cvGet2D(img,center.y, center.x);//colour of circle 
    printf("B: %f G: %f R: %f\n",s.val[0],s.val[1],s.val[2]); 
} 

答えて

2

pyrDownまたはresizeのいずれかでHoughCirclesでそれを処理する前に画像のサイズを減らしてみてください。

検出された円を元の画像で使用する場合は、半径と中心に画像を分割した係数を掛けます。 2倍の縮尺では、処理時間からスケール操作を実行するのにかかる時間を引いた2倍から4倍のスピードアップが得られます。

以下

あなたがこのことについてに行くかもしれない方法の簡単な例です:

#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(int argc, char** argv) 
{ 
    Mat circleBig = imread("circle.png", 0); 
    Mat circleSmall; 

    double scale = 2.0; 

    // INTER_NEAREST is crude, but very fast; you may need INTER_LINEAR here... 
    resize(circleBig, circleSmall, Size(0, 0), 1.0/scale, 1.0/scale, cv::INTER_NEAREST); 

    cvtColor(circleBig, circleBig, CV_GRAY2RGB); 

    vector<Vec3f> circles; 
    HoughCircles(circleSmall, circles, CV_HOUGH_GRADIENT, 2, circleSmall.rows >> 2, 200, 100); 

    for(size_t i = 0; i < circles.size(); i++) 
    { 
     Point center(cvRound(circles[i][0]), cvRound(circles[i][3])); 
     int radius = cvRound(circles[i][4]); 
     // draw the circle center 
     circle(circleBig, scale*center, 3, Scalar(0,255,0), -1, 8, 0); 
     // draw the circle outline 
     circle(circleBig, scale*center, scale*radius, Scalar(0,0,255), 3, 8, 0); 
    } 

    imshow("circleBig", circleBig); 
    waitKey(); 

    return 0; 
} 

は最後に、ここで私が使用したテスト画像である: circle.png

ここで私はHoughCircles検出になったタイミングがあります:

640x480 time: 0.0127101 
320x240 time: 0.00408843 

大体3倍のスピードアップ! :)

+0

私は上記の私のコードを入れました。どのようにビデオ全体のサイズを変更しますか? –

+0

'HoughCircles'関数を呼び出す前に一度に1フレームずつサイズを変更するだけです。処理を開始する前にビデオ全体のサイズを変更する必要はないので、 'img'マトリックスを' imgSmall'マトリックスにリサイズし、私の例のように 'imgSmall'で' HoughCircles'を計算します。 – mevatron

+0

だからちょうどresize(circleBig、circleSmall、Size(0、0)、1.0/scale、1.0/scale、cv :: INTER_NEAREST);後でcvQueryFrame(キャプチャ) –

0

私はmevatronの提案を試すことができます、それは確かに違いを生むだろうと私はそれをupvoted理由です。

しかし、あなたに明確にする必要のあるものは次のとおりです。ビデオのスローダウンはソースコードのバグではなく、OpenCVのバグでもありません。この効果は、ビデオのすべてのフレームに対してサークル検出を実行するためにCPUが処理時間を費やす必要があるために発生します。あなたのCPUは、あなたにリアルタイムの感覚を与えるのに十分速くこのタスクを実行することはできません。

OpenCVでAVIを再生しているだけではないので、質問のタイトルは少し誤解を招くことがあります。

関連する問題