ブログ

OpenCVでテンプレートマッチング

at_nakai
2014年5月28日 11時34分

OpenCVでテンプレートマッチングを行うソースコードを作ったのでシェアします。

解析結果を合成した画像を/tmp/result.jpgに生成するようにしてあります。 mjpeg_streamerのinput_file.soなどと組み合わせることで、結果を簡単に確認することができます。

Makefile

CROSS_COMPILE ?= arm-linux-gnueabihf-
 
CC = $(CROSS_COMPILE)gcc
CFLAGS = -Wall -O2
 
EXEC = template_match
OBJS = template_match.o
LDLIBS := -lopencv_core -lopencv_highgui -lopencv_imgproc -lm
 
all: $(EXEC)
 
$(EXEC): $(OBJS)
    $(CC) $(LDFLAGS) -o $@ $(OBJS) $(LDLIBS)
 
romfs:
    $(ROMFSINST) /usr/bin/$(EXEC)
 
clean:
    rm -f $(OBJS) $(EXEC)

template_match.c

#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <opencv/cv.h>
#include <opencv/highgui.h>
 
void myOutputInit(char *wname)
{
#ifndef __arm__
    cvNamedWindow(wname, CV_WINDOW_AUTOSIZE);
#endif
}
 
void myOutput(char *wname, IplImage *output)
{
#ifdef __arm__
    cvSaveImage("/tmp/result.jpg", output, NULL);
#else
    cvShowImage(wname, output);
    cvWaitKey(10);
#endif
}
 
void myOutputRelease(char *wname)
{
#ifndef __arm__
    cvDestroyWindow(wname);
#endif
}
 
IplImage *match_func(IplImage *testimg, IplImage *templateimg,
                 IplImage *outputimg)
{
    IplImage *resultimg;
    double maxval;
    CvPoint maxloc;
    clock_t start, end;
 
    resultimg = cvCreateImage(cvSize(testimg->width - templateimg->width + 1, testimg->height - templateimg->height + 1), 32, 1);
 
    start = clock();
    cvMatchTemplate(testimg, templateimg, resultimg, CV_TM_CCOEFF_NORMED);
    end = clock();
    printf("processing time: %.2f [s]\n",
           (double)(end - start) / CLOCKS_PER_SEC);
 
    cvMinMaxLoc(resultimg, NULL, &maxval, NULL, &maxloc, NULL);
    printf("(%3d,%3d), score=%f\n", maxloc.x, maxloc.y, maxval);
    cvCopy(testimg, outputimg, NULL);
 
    if (maxval > 0.25)
        cvRectangle(outputimg, maxloc,
                cvPoint(maxloc.x + templateimg->width,
                    maxloc.y + templateimg->height),
                CV_RGB(255, 0, 0), 3, 8, 0);
 
    cvReleaseImage(&resultimg);
 
    return outputimg;
}
 
int main(int argc, char *argv[])
{
    IplImage *testimg, *templateimg, *outputimg;
    CvCapture *capture;
    int video_dev = 0;
    char templateimgfile[] = "template.jpg";
    int i;
 
    if (argc > 1)
        video_dev = atoi(argv[1]);
 
    capture = cvCreateCameraCapture(video_dev);
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 320);
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 240);
 
    if ((testimg = cvQueryFrame (capture)) == NULL) {
        fprintf(stderr, "camera device not found.\n");
        return -EIO;
    }
 
    templateimg = cvLoadImage(templateimgfile,
                  (CV_LOAD_IMAGE_ANYCOLOR |
                   CV_LOAD_IMAGE_ANYDEPTH));
 
    outputimg = cvCreateImage(cvGetSize(testimg), IPL_DEPTH_8U, 3);
 
    myOutputInit("Output1");
 
    for (i=0; ; i++) {
        testimg = cvQueryFrame(capture);
        if (testimg == NULL) {
            fprintf(stderr, "failed to query frame.\n");
            return -EIO;
        }
 
        outputimg = match_func(testimg, templateimg, outputimg);
 
        myOutput("Output1", outputimg);
    }
 
    myOutputRelease("Output1");
 
    cvReleaseImage(&outputimg);
    cvReleaseImage(&templateimg);
    cvReleaseImage(&testimg);
 
    return 0;
}