Ask Your Question
1

How to convert cv::Mat to std::string and hash it using MD5 ?

asked 2013-09-20 02:55:56 -0600

tomriddle gravatar image

updated 2013-09-20 03:15:04 -0600

berak gravatar image

I need to find the repeated images (exact same, this is not a image similarity problem) by hashing. So I tried something like this, but this seems not right.

Mat src = imread (inputfile, -1) ;

char* rawPtr = new char[src.step[0] * src.rows] ;
memcpy(rawPtr, (char*)src.data, src.step[0] * src.rows) ; // is this all the data ??
string rawdata(rawPtr) ;

cout << str2md5(rawPtr, strlen(rawPtr)) << endl ;

My file is CV_16UC3, 1624 by 1236 , 3 channels, src.step[0] * src.rows is the bytes number of the whole image 12043584 bytes, however strlen(rawPtr) returns 5739852 chars, and these don't match.

So the md5 value I got is not right. I would like to know how to efficiently and correctly convert cv::Mat data into a string.

edit retag flag offensive close merge delete

Comments

1

rrrr, you can't use strlen (or , any string related function) on binary data ! ( as it will stop at the 1st 0, which is the string terminator, but a total valid black pixel )

use the same length calculation (src.step[0] * src.rows) you had before instead.

making a string of it won't work as expected, too, for the same reason.

if your str2md5 function expects a const char * as input, it might work, if it wants a std::string, it won't.

berak gravatar imageberak ( 2013-09-20 03:10:29 -0600 )edit

@berak, thanks so much, I didn't realize it. But I am still not sure if I'm doing it right to hash the cv::Mat. I got another example here . FileStorage fs (".xml", FileStorage::WRITE + FileStorage::MEMORY) ; fs <<"data"<< src ; string cvinternal = fs.releaseAndGetString() ; //cout << cvinternal.length() << endl ; cout << str2md5(cvinternal.c_str(), cvinternal.length()) << endl ;

How do you think use this to hash ?

tomriddle gravatar imagetomriddle ( 2013-09-22 18:56:57 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2013-09-22 22:58:54 -0600

tomriddle gravatar image

Worked it out.

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <functional>
#include <openssl/md5.h>

using namespace std;
using namespace cv;

static void help()
{
}

char *str2md5(const char *str, int length) {
    int n;
    MD5_CTX c;
    unsigned char digest[16];
    char *out = (char*)malloc(33);

    MD5_Init(&c);

    while (length > 0) {
        if (length > 512) {
            MD5_Update(&c, str, 512);
        } else {
            MD5_Update(&c, str, length);
        }
        length -= 512;
        str += 512;
    }

    MD5_Final(digest, &c);

    for (n = 0; n < 16; ++n) {
        snprintf(&(out[n*2]), 16*2, "%02x", (unsigned int)digest[n]);
    }

    return out;
}


int main(int argc, const char** argv)
{
    help();

    if (argc != 2)
    {
        return EXIT_FAILURE ;
    }

    string inputfile = argv[1] ;

    Mat src = imread (inputfile, -1) ;

    if (src.empty())
    {
        return EXIT_FAILURE ;
    }



    cout << str2md5((char*)src.data, (int)src.step[0] * src.rows) << " " << inputfile << endl ;




    return 0;
}
edit flag offensive delete link more

Question Tools

Stats

Asked: 2013-09-20 02:55:56 -0600

Seen: 3,808 times

Last updated: Sep 22 '13