Image Feature Extraction and Matching with OpenCV

目前图像识别仍然是一个重要的研究课题,主要用到的图像匹配方法有颜色直方图、模版匹配、特征匹配等。特征匹配是目前主流的也是准确率较高的匹配方式,例如Google、百度等主流搜索引擎的图像搜索。
下面是使用OpenCV实现的一个简单的图像特征匹配程序

main.cpp

#include <cstdio>
#include <iostream>
#include <opencv2/opencv.hpp>
#include "feature.h"

using namespace cv;
using namespace std;

int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        cout << "wrong usage!" << endl;
        cout << "usage: ./bin queryImage trainImage" << endl;
        return -1;
    }

    string detectorType = "SURF";
    string extractorType = "SIFT";
    string detectors[] = {"SIFT", "SURF", "SURF", "MSER", "STAR", "HARRIS", "FAST"};
    string extractors[] = {"SIFT", "SURF", "SIFT", "SIFT", "SIFT", "SIFT", "SIFT"};
    string matchType = "FlannBased";
    string queryImagePath = argv[1];
    string trainImagePath = argv[2];

    Mat queryImage = imread(queryImagePath, CV_LOAD_IMAGE_GRAYSCALE);
    Mat trainImage = imread(trainImagePath, CV_LOAD_IMAGE_GRAYSCALE);
    if (queryImage.empty() || trainImage.empty())
    {
        cout<<"read failed"<< endl;
        return -1;
    }

    for(int i = 0; i < 7; ++i)
    {
        string detectorType = detectors[i];
        string extractorType = extractors[i];

        Feature feature(detectorType, extractorType, matchType);

        vector<KeyPoint> queryKeypoints, trainKeypoints;
        feature.detectKeypoints(queryImage, queryKeypoints);
        feature.detectKeypoints(trainImage, trainKeypoints);

        Mat queryDescriptor, trainDescriptor;

        feature.extractDescriptors(queryImage, queryKeypoints, queryDescriptor);
        feature.extractDescriptors(trainImage, trainKeypoints, trainDescriptor);

        vector<DMatch> matches;
        feature.bestMatch(queryDescriptor, trainDescriptor, matches);

        double max_dist = 0;
        double min_dist = 100;

        for(int i = 0; i < queryDescriptor.rows; ++i)
        {
            double dist = matches[i].distance;
            if(dist < min_dist) min_dist = dist;
            if(dist > max_dist) max_dist = dist;
        }
        //printf("-- Min dist: %f \n", min_dist);
        //printf("-- Max dist: %f \n", max_dist);

        vector< DMatch > good_matches;
        for(int i = 0; i < queryDescriptor.rows; ++i)
        {
            if( matches[i].distance <= max(2*min_dist, 0.02) )
            {
                good_matches.push_back(matches[i]);
            }
        }
        feature.saveMatches(queryImage, queryKeypoints, trainImage, trainKeypoints, good_matches, "./");
    }
	  printf("Done\n");
    return 0;
}

read more

My PHP Android Develop Problem List

The following is some problems what I encountered in the PHP and Android development and solutions.

1. How to upload file to PHP server from Android.

Java code:

HttpClient httpclient = new DefaultHttpClient();
httpclient.getParams().setParameter(CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1);
try{
	HttpPost httppost = new HttpPost("url");
	FileBody imageBody = new FileBody(new File("file path"));
	StringBody typeBody = new StringBody("image", ContentType.TEXT_PLAIN);
	HttpEntity reqEntity = MultipartEntityBuilder.create()
		.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
		.addPart("file", imageBody)
		.addPart("filetype", typeBody).build();
	httppost.setEntity(reqEntity);
	Log.i("DEBUG", "executing request " + httppost.getRequestLine());
	HttpResponse httpResponse = httpclient.execute(httppost);
	HttpEntity resEntity = httpResponse.getEntity();
	if (resEntity != null) {
		String strResult = EntityUtils.toString(resEntity, "UTF-8");
                Log.i("DEBUG", strResult);
	}
			
}catch (Exception e) {
	// TODO Auto-generated catch block
	e.printStackTrace();
}

read more

Making a plugin for R using C

R语言虽然很强大,但是它有一个缺点:for循环非常慢。我们知道C是很快的,那我们是不是可以用C来弥补R的这个缺陷呢?是的,我们可以。
编写R代码
先看一段R代码,这是一个函数,里面有个双重循环

foo<-function(N,a,b)
{
    c<-numeric(N);

    for(i in 1:N)
    {
        for(j in 1:N)
        {
             c[i] = a[i] * b[j];
        }
    }
   return(c)
}

调用这个函数

>foo(N=4, a=c(1,2,3,4), b=c(5,6,7,8))
[1] 8 16 24 32

编写C代码
然后,我们用C实现同样的函数

void foo(int *N, double *A, double *B, double *C)
{
    int n = *N;
    for(int i = 0; i < n; i++)
    {
         for(int j = 0; j < n; j++)
         {
              C[i] = A[i] * B[j];
         }
    }
}

验证一下这个foo函数有没有错误

int main(int argc, char *argv[])
{
	int *N = (int*)malloc(sizeof(int)*1);
	double *a = (double*)malloc(sizeof(double)*4);
	double *b = (double*)malloc(sizeof(double)*4);
	double *c = (double*)malloc(sizeof(double)*4);
	
	N[0] = 4;
	
	a[0] = 1;
	a[1] = 2;
	a[2] = 3;
	a[3] = 4;
	
	b[0] = 5;
	b[1] = 6;
	b[2] = 7;
	b[3] = 8;
	
	foo(N,a,b,c);
	
	printf("c: %f %f %f %f\n", c[0], c[1], c[2], c[3]);
	
	return EXIT_SUCCESS;
}

read more