meanshift アルゴリズムを使用して移動オブジェクトを追跡したい。このために、まず背景からフレームを差し引きます。次に、侵食、膨張、および平滑化が適用されます。動く物体を検出し、その座標を見つけるために、コーナーポイント検出を使用しています。
次に、コーナーポイントの平均を計算し、これらのポイントを平均シフト検索ウィンドウに渡します。オブジェクトが画面に表示されると、プログラムはコーナーポイント検出を終了し、平均シフト追跡に入ります。オブジェクトが画面を離れるまで、平均シフトで実行され続けます。
オブジェクトが画面から離れたら、コーナー ポイントの検出を再度有効にします。このために、プログラムを meanshift から取り出し、コーナー ポイント検出に戻ります。プログラムは正常に実行されていますが、問題は、平均シフトを離れてコーナーポイント検出に再び入ると、数秒間スタックすることです。
その後は順調に走っています。この問題は、平均シフトからコーナー ポイント検出への移行中にのみ発生します。考えられる理由はわかりません。どなたか解決策を教えてください。
これが私のコードです:
#include "highgui.h"
#include "cv.h"
#include "cxcore.h"
#include "cvaux.h"
#include <iostream>
using namespace std;
const int MAX_CORNERS = 500;
inline static void allocateOnDemand(IplImage** img, CvSize size, int depth, int channels) {
if (*img != NULL)
return;
*img = cvCreateImage(size, depth, channels);
if (*img == NULL) {
fprintf(stderr, "Error: Couldn't allocate image. Out of memory?\n");
exit(-1);
}
}
int main() {
CvCapture* capture = cvCaptureFromCAM(CV_CAP_V4L2);
IplImage* pFrame[10];
IplImage* bg;
IplImage* img_A;
IplImage* img_B;
IplImage* eig_image;
IplImage* tmp_image;
img_A = cvQueryFrame(capture);
CvSize img_sz = cvGetSize(img_A);
int c1 = 0, c2 = 0;
int xarr[40];
//A temporary replacement for background averaging
int j = 0;
for (j = 0; j < 10; j++) {
pFrame[j] = cvQueryFrame(capture);
cvWaitKey(200);
}
cvSaveImage("10.jpg", pFrame[9], 0); //saving the background
IplImage* imgA = cvCreateImage(cvGetSize(img_A), 8, 1);
IplImage* imgB = cvCreateImage(cvGetSize(img_A), 8, 1);
IplImage* imgB1 = cvCreateImage(cvGetSize(img_A), 8, 1);
IplImage* imgb = cvCreateImage(cvGetSize(img_A), 8, 1);
cvNamedWindow("LKpyr_OpticalFlow", CV_WINDOW_AUTOSIZE);
bg = cvLoadImage("10.jpg", CV_LOAD_IMAGE_GRAYSCALE); //loading the saved background
int flag = 0;
int index = 0;
char keypress;
bool quit = false;
CvConnectedComp*out = new CvConnectedComp(); //output window for meanshift
int win_size = 25; //window size for corner point detection
int x1 = 0;
int y1 = 0;
int x;
int y;
int cc;
line3:
while (quit == false) { //line3:
IplImage* imgC = cvCreateImage(cvGetSize(img_A), 8, 1); //creating output image
cvZero(imgC);
img_B = cvQueryFrame(capture);
imgC = cvQueryFrame(capture);
// line3:
int corner_count = MAX_CORNERS; //total no of corners found in frame
cvCvtColor(img_B, imgb, CV_BGR2GRAY);
//line3:
CvPoint2D32f* cornersA = new CvPoint2D32f[MAX_CORNERS];
CvPoint2D32f* cornersB = new CvPoint2D32f[MAX_CORNERS];
if (index % 2 == 0) {
cvSub(imgb, bg, imgB, NULL); //background subtraction and stuff
cvErode(imgB, imgB, NULL, 4);
cvDilate(imgB, imgB, 0, 2);
cvSmooth(imgB, imgB, 0, 1);
cvThreshold(imgB, imgB, 50, 255, CV_THRESH_BINARY);
//line3:
if (flag == 1) goto line1; //Go to Meanshift
allocateOnDemand(&eig_image, img_sz, IPL_DEPTH_32F, 1);
allocateOnDemand(&tmp_image, img_sz, IPL_DEPTH_32F, 1);
cvCvtColor(img_A, imgA, CV_BGR2GRAY);
//line3:
cvGoodFeaturesToTrack(imgB, eig_image, tmp_image, cornersA, &
corner_count, 0.05, 5.0, 0, 3, 0, 0.04); //detects corners and no of corners stored in corner_count
cvFindCornerSubPix(imgB, cornersA, corner_count, cvSize(12, 12),
cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER |
CV_TERMCRIT_EPS, 20, 0.03));
CvPoint p0;
CvPoint p1;
CvPoint acc;
cc = corner_count + 20;
acc.x = 0;
acc.y = 0;
for (int i = 0; i < corner_count; i++) {
p0 = cvPoint(cvRound(cornersA[i].x), cvRound(cornersA[i].y));
p1 = cvPoint(cvRound(cornersB[i].x), cvRound(cornersB[i].y));
acc.x = acc.x + p0.x; //calculating mean of corner points
acc.y = acc.y + p0.y;
}
delete[] cornersA;
delete[] cornersB;
cout << "Corner Count is" << corner_count << endl;
cout << "Flag status: " << flag << endl;
if (corner_count > 0) {
flag = 1;
cvWaitKey(20);
}
x1 = cvRound(acc.x / (corner_count + 1));
y1 = cvRound(acc.y / (corner_count + 1));
cout << "x is " << x1 << " y is " << y1 << endl;
cout << "Flag status: " << flag << endl;
x = x1;
y = y1;
if (flag == 0) goto line2; //Go back to Corner Point detection
line1: CvRect window = cvRect(x, y, 80, 90); //Creates window for meanshift algo
cvMeanShift(imgB, window, cvTermCriteria(CV_TERMCRIT_EPS |
CV_TERMCRIT_ITER, 200, 1), out);
window = out->rect;
x = out->rect.x;
y = out->rect.y;
cout << "Now x is " << x << " y is " << y << endl;
cout << "Flag status: " << flag << endl;
if (out->area > 200) {
cvRectangle(imgC, cvPoint(x + 50, y + 100), cvPoint(x - 20, y -
90), cvScalar(0, 0, 255), 3, 8, 0);
} else {}
xarr[c1] = x;
c1++;
if (c1 > 39) c1 = 0;
if (xarr[0] == xarr[39]) {
c2 = 1;
cout << "c2 is now " << c2 << endl;
}
}
if (x == 0 || y == 0 || x < 7 || x > 572 || c2 == 1) {
flag = 0;
c2 = 0;
goto line3;
break;
}
line2: cvShowImage("LKpyr_OpticalFlow", imgC);
keypress = cvWaitKey(20);
// Set the flag to quit if escape was pressed
if (keypress == 27) {
quit = true;
}
//index++;
} //end of while
return 0;
}