Ask Your Question
0

Flann index for video duplicate finding

asked 2016-01-06 12:14:29 -0600

phirestalker gravatar image

updated 2016-01-10 02:01:25 -0600

I am writing a program to find duplicate videos, I am pulling frames every 500ms and using ORB to compute. I was looking at using FLANN for matching and heard about index. Reading further it says that you sacrifice accuracy, but I wonder how much. Since I am matching videos I only want 95% or higher matches of frames and will determine video matches by how many frames in common at that accuracy.

EDIT: I have been reading and see that orb is a binary descriptor and the flann matcher I was thinking of using is not for binary descriptors. Does the index even work with binary descriptors? Do I need an index or is matching binary descriptors by hamming distance fast enough not to need one?

edit retag flag offensive close merge delete

Comments

1
Eduardo gravatar imageEduardo ( 2016-01-09 12:05:11 -0600 )edit

those help, but what I really need now is some documentation on how to build the index with more than one image. I know it takes descriptors in the arguments, but can this be an array of arrays so each images descriptors are separate enough to tell which files match?

phirestalker gravatar imagephirestalker ( 2016-01-12 15:38:59 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2016-02-03 20:03:44 -0600

phirestalker gravatar image

updated 2016-02-03 20:08:59 -0600

ok I figured it out this code should work when plugged with a qstringlist of files

QStringList videos;
Mat indexTemp;
struct frm
{
    QString file;
    int position;
    cv::Mat descriptors;
};
QList<frm> frames;

foreach (video, videos)
{
    process(video);
}

for (i = 0; i < indexTemp.rows; i++)
{
    Mat mat = indexTemp.row(i);
    Mat indices;
    Mat dists;
    int k = 3;
    if (!mat.isContinuous() || mat.empty())
        return;
    try
    {
        mat = mat.reshape(1,1);
        index.knnSearch(mat,indices,dists,k);
    }
    catch (Exception e)
    {
        qWarning() << "index search failure" << e.err.c_str() << e.msg.c_str();
    }
    catch (exception& e)
    {
        qWarning() << "index search failure" << e.what();
    }
    for (int j = 0; j < indices.cols; j++)
    {
        if (indices.at<int>(0,i) == -1 || dists.at<int>(0,j) < 12800) //knnsearch returns -1 for all cols after the matches it was able to find. 12800 is about 90% match with 500 ORB descriptors
            continue;
        try
        {
            QTime matchtime(0,0,0,0);
            int matchms = frames.at(i).position;
            matchtime = matchtime.addMSecs(matchms);
            int temp = dists.at<int>(0,j);
            qDebug() << frames.at(i).file << "frame"<<  timestamp.toString("hh:mm:ss") << "match at"<< frames.at(indices.at<int>(0,j)).file << matchtime.toString("hh:mm:ss") << "distance" << temp;
        }
        catch (Exception e)
        {
            qWarning() << "failure in indices" << e.err.c_str() << e.msg.c_str() << e.func.c_str();
        }
        catch (exception &e)
        {
            qWarning() << "failure in indices" << e.what();
        }
    }
}
index.build(indexTemp,cv::flann::LshIndexParams(12,20,3), cvflann::FLANN_DIST_HAMMING);


void process(Qstring video)
{
    if (video.isEmpty())
        return;
    int interval = 500;
    int current_interval = 0;
    UMat frame;
    vector< cv::KeyPoint > keypoints;
    Ptr<DescriptorExtractor> odetector = cv::ORB::create(500);
    UMat imgDescriptor;
    VideoCapture videocap(video.toStdString());
    if (!videocap.isOpened())
    {
        failedstream << video << " could not be opened. Check permissions" << endl;
        return;
    }
    for(; ; )
    {
        if (current_interval != 0)
            videocap.set(CV_CAP_PROP_POS_MSEC,current_interval);
        if (current_interval > videocap.get(CV_CAP_PROP_POS_MSEC) + 400) // I found some videos needed this in case the last from is not quite 500 ms away from the previous one
            break;
        if (!videocap.read(frame))
            break;
        current_interval += interval;
        if (frame.empty() || !frame.isContinuous()) //skipping bad frames
            continue;
        odetector->detect(frame,keypoints);
        odetector->compute(frame,keypoints,imgDescriptor);
        if (imgDescriptor.empty() || !imgDescriptor.isContinuous()) // don't ask me how but even with all the frame checking this is still needed
        {
            qDebug() << "descriptors empty or corrupted" << imgDescriptor.empty() << imgDescriptor.isContinuous();
            continue;
        }
        {
        Mat imgDescriptorMat = imgDescriptor.getMat(cv::ACCESS_RW);
        Mat matonerow;
        frm tmp;
        tmp.file = video;
        tmp.position = current_interval;
        if (imgDescriptorMat.rows < 500)
            imgDescriptorMat.push_back(Mat::zeros((500 - imgDescriptorMat.rows),32,CV_8U));
        matonerow = imgDescriptorMat.reshape(1,1);
        indexTemp.push_back(matonerow);
        imgDescriptorMat.copyTo(tmp.descriptors);
        frames.append(tmp);
    }
}
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-01-06 12:14:29 -0600

Seen: 440 times

Last updated: Feb 03 '16