Ask Your Question
0

Improve the accuacy of image matching algorithm?

asked 2014-11-18 12:31:59 -0600

updated 2014-11-19 07:49:07 -0600

Doombot gravatar image

I am new to openCV. I am going to write a program to retrieve the best matched image from the image database given an input image. However, I found that the accuracy is quite low. A low percentage of images can be correctly matched from the database. The program can run, but I am not satisfied with that.

What are the problems in the algorithm? Which parts do I need to improve? And how can I improve it? Thanks guys.

 #include "opencv2/highgui/highgui.hpp"
 #include "opencv2/imgproc/imgproc.hpp"  
 #include <iostream>  
 #include <stdio.h>  
 #include <algorithm>  

using namespace std;
using namespace cv;

#define IMAGE_LIST_FILE "inputimage.txt"

/**
 * @function main
 */

//Compute pixel-by-pixel difference
double compareImgs(Mat img1, Mat img2)
{
    int w = img1.cols, h = img2.rows;
    Mat new_img2;
    resize(img2, new_img2, img1.size());
    double sum = 0;
    for (int i = 0; i < w; i++)for (int j = 0; j < h; j++)
    {
        sum += abs(img1.at<uchar>(j, i) - new_img2.at<uchar>(j, i));
    }
    return sum;
}

int main( int argc, char** argv )

{

Mat src_input, gray_input;  
Mat db_img, db_gray_img;

double score[1000];
int db_id = 0;
double maxscore = 1000000000;
int maxscore_num;
char maximg_name[200];
Mat max_img;

src_input = imread("dinosaur.jpg"); // read input image
if( !src_input.data )
{
    printf("Cannot find the input image!\n");
    system("pause");
    return -1; 
}
imshow("Input",src_input);
/// Convert to grayscale
cvtColor(src_input, gray_input, COLOR_BGR2GRAY);

///Read Database
FILE   *fp; 
char imagepath[200];
fp   =   fopen( IMAGE_LIST_FILE, "r ");
printf("Extracting features from input images...\n");
while(!feof(fp))
{
   while(fscanf(fp,   "%s ",   imagepath)   >   0) 
   {
       printf("%s\n",imagepath);
       char tempname[200];
       sprintf_s(tempname,200,"../%s",imagepath);

       db_img = imread(tempname); // read database image
       if( !db_img.data )
       {
           printf("Cannot find the database image number %d!\n",db_id+1);
           system("pause");
           return -1; 
       }

       cvtColor(db_img, db_gray_img, COLOR_BGR2GRAY);

       /// Apply the pixel-by-pixel comparison method
       score[db_id] = compareImgs(gray_input, db_gray_img);
       /// Compute max score
       if(score[db_id]<maxscore)
       {
           maxscore=score[db_id];
           maxscore_num = db_id;
           memcpy(maximg_name,tempname,200*sizeof(char));
       }
       db_id++; 
   }
} 
fclose(fp);

Mat maximg = imread(maximg_name);
imshow("Best Match Image",maximg);

printf("the most similar image is %d, the pixel-by-pixel difference is %f\n",maxscore_num+1, maxscore);

printf( "Done \n" );
// Wait for the user to press a key in the GUI window.
//Press ESC to quit
int keyValue=0;
while(keyValue>=0)
{
    keyValue=cvWaitKey(0);

    switch(keyValue)
    {
    case 27:keyValue=-1;
        break;  
    }
}

return 0;

}

edit retag flag offensive close merge delete

2 answers

Sort by ยป oldest newest most voted
1

answered 2014-11-19 08:25:37 -0600

Doombot gravatar image

This will be in two parts. First, give a look at the function absdiff . It might very well replace your compareImgs(), give a look at it (maybe not, just give a look). Personally, I have lost some time in the past trying to implement some function that where already present in OpenCV, C++, etc. Still, if you don't know a function exists, how do you look for it? I am no better than anyone at this, sometime I just ask on this site! ;)

Second: You need to understand (or state explicitly if you do) what type of comparison you are doing. I'll ask some question and just think about them, you might as well have good reasons for doing the way you have done.

  • You have a src_input that you convert to grayscale. Why? Comparing greyscale vs a 3 channels BGR (OpenCV reverse the order of RGB for some historical reason) is shorter, but converting from BRG takes time too. By going greyscale, you are losing information. Do you think scraping the colour is relevant for a comparison? Maybe yes, maybe no. More on this later.

  • Same thing for the db_img.

  • What is the relation between the database and your src_img? Is it a database including a mix of different stuff, or at the opposite is it a database that includes 1000 minor variations of the same image? I mean, a pixel by pixel comparison can only go as far as telling you up to which point two images are perfectly identical. Should your src_img be shifted by one row of pixel, it would dramatically decrease the match. If shifted by 2 rows, worse. (You can imagine that by shifting by a row, I mean any even small difference in your src_image that would defeat a px by px comparison).

  • If you do indeed need to do a px by px comparison, you should consider to branch out (break;) from your loop after some number of mismatch; I mean if you scan the whole top quarter of the image (or even less) and the matching is no good, don't bother matching the rest...

  • If your expect some difference in px between the src_img and the database, you should try alternate strategies such as computing the histogram of each image of the database and to histogram matching

I hope this bag of comment will help you. If you need any more info, feel free to ask in the comments!

edit flag offensive delete link more
0

answered 2014-11-21 02:30:07 -0600

Sorry, I am not to answer what you are explicity asking for, but I want you to know about CBIR, because I think this is the right thing you are trying to implement.

"to retrieve the best matched image from the image database given an input image"

You should clearly define what is the best matched image, because identifying best match could be based on: low-level features (color, image descriptors, etc)
or high-level features (represents semantically meaningful concepts in the image). This is called semantic gap (http://en.wikipedia.org/wiki/Semantic_gap)

I recommend you to read about CBIR (Content-based Image Retrieval). Here for example, is the list of CBIR engines. This list can give you a quick start: http://en.wikipedia.org/wiki/List_of_CBIR_engines

edit flag offensive delete link more

Question Tools

Stats

Asked: 2014-11-18 12:31:59 -0600

Seen: 883 times

Last updated: Nov 21 '14