コード例 #1
0
ファイル: opencvalgorithms.cpp プロジェクト: niconil/actionaz
    MatchingPointList OpenCVAlgorithms::fastMatchTemplate(const QList<cv::Mat> &sources,
                                                                            const cv::Mat &target,
																			int matchPercentage,
																			int maximumMatches,
																			int downPyrs,
                                                                            int searchExpansion,
                                                                            AlgorithmMethod method)
	{
        MatchingPointList matchingPointList;
        int sourceIndex = 0;

        foreach(const cv::Mat &source, sources)
        {
            try
            {
                // create copies of the images to modify
                cv::Mat copyOfSource = source.clone();
                cv::Mat copyOfTarget = target.clone();

                cv::Size sourceSize = source.size();
                cv::Size targetSize = target.size();

                // down pyramid the images
                for(int ii = 0; ii < downPyrs; ii++)
                {
                    // start with the source image
                    sourceSize.width  = (sourceSize.width  + 1) / 2;
                    sourceSize.height = (sourceSize.height + 1) / 2;

                    cv::Mat smallSource(sourceSize, source.type());
                    cv::pyrDown(copyOfSource, smallSource);

                    // prepare for next loop, if any
                    copyOfSource = smallSource.clone();

                    // next, do the target
                    targetSize.width  = (targetSize.width  + 1) / 2;
                    targetSize.height = (targetSize.height + 1) / 2;

                    cv::Mat smallTarget(targetSize, target.type());
                    pyrDown(copyOfTarget, smallTarget);

                    // prepare for next loop, if any
                    copyOfTarget = smallTarget.clone();
                }

                // perform the match on the shrunken images
                cv::Size smallTargetSize = copyOfTarget.size();
                cv::Size smallSourceSize = copyOfSource.size();

                cv::Size resultSize;
                resultSize.width = smallSourceSize.width - smallTargetSize.width + 1;
                resultSize.height = smallSourceSize.height - smallTargetSize.height + 1;

                cv::Mat result(resultSize, CV_32FC1);
                cv::matchTemplate(copyOfSource, copyOfTarget, result, toOpenCVMethod(method));

                // find the top match locations
                QVector<QPoint> locations = multipleMinMaxLoc(result, maximumMatches, method);

                // search the large images at the returned locations
                sourceSize = source.size();
                targetSize = target.size();

                int twoPowerNumDownPyrs = std::pow(2.0f, downPyrs);

                // create a copy of the source in order to adjust its ROI for searching
                for(int currMax = 0; currMax < maximumMatches; ++currMax)
                {
                    // transform the point to its corresponding point in the larger image
                    QPoint &currMaxLocation = locations[currMax];
                    currMaxLocation *= twoPowerNumDownPyrs;
                    currMaxLocation.setX(currMaxLocation.x() + targetSize.width / 2);
                    currMaxLocation.setY(currMaxLocation.y() + targetSize.height / 2);

                    const QPoint &searchPoint = locations.at(currMax);

                    // if we are searching for multiple targets and we have found a target or
                    //  multiple targets, we don't want to search in the same location(s) again
                    if(maximumMatches > 1 && !matchingPointList.isEmpty())
                    {
                        bool thisTargetFound = false;

                        for(int currPoint = 0; currPoint < matchingPointList.size(); currPoint++)
                        {
                            const QPoint &foundPoint = matchingPointList.at(currPoint).position;
                            if(std::abs(searchPoint.x() - foundPoint.x()) <= searchExpansion * 2 &&
                               std::abs(searchPoint.y() - foundPoint.y()) <= searchExpansion * 2)
                            {
                                thisTargetFound = true;
                                break;
                            }
                        }

                        // if the current target has been found, continue onto the next point
                        if(thisTargetFound)
                            continue;
                    }

                    // set the source image's ROI to slightly larger than the target image,
                    //  centred at the current point
                    cv::Rect searchRoi;
                    searchRoi.x = searchPoint.x() - (target.size().width) / 2 - searchExpansion;
                    searchRoi.y = searchPoint.y() - (target.size().height) / 2 - searchExpansion;
                    searchRoi.width = target.size().width + searchExpansion * 2;
                    searchRoi.height = target.size().height + searchExpansion * 2;

                    // make sure ROI doesn't extend outside of image
                    if(searchRoi.x < 0)
                        searchRoi.x = 0;

                    if(searchRoi.y < 0)
                        searchRoi.y = 0;

                    if((searchRoi.x + searchRoi.width) > (sourceSize.width - 1))
                    {
                        int numPixelsOver = (searchRoi.x + searchRoi.width) - (sourceSize.width - 1);

                        searchRoi.width -= numPixelsOver;
                    }

                    if((searchRoi.y + searchRoi.height) > (sourceSize.height - 1))
                    {
                        int numPixelsOver = (searchRoi.y + searchRoi.height) - (sourceSize.height - 1);

                        searchRoi.height -= numPixelsOver;
                    }

                    cv::Mat searchImage(source, searchRoi);

                    // perform the search on the large images
                    resultSize.width = searchRoi.width - target.size().width + 1;
                    resultSize.height = searchRoi.height - target.size().height + 1;

                    result = cv::Mat(resultSize, CV_32FC1);
                    cv::matchTemplate(searchImage, target, result, toOpenCVMethod(method));

                    // find the best match location
                    double minValue;
                    double maxValue;
                    cv::Point minLoc;
                    cv::Point maxLoc;

                    cv::minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc);

                    double &value = (method == SquaredDifferenceMethod) ? minValue : maxValue;
                    cv::Point &loc = (method == SquaredDifferenceMethod) ? minLoc : maxLoc;

                    value *= 100.0;

                    // transform point back to original image
                    loc.x += searchRoi.x + target.size().width / 2;
                    loc.y += searchRoi.y + target.size().height / 2;

                    if(method == SquaredDifferenceMethod)
                        value = 100.0f - value;

                    if(value >= matchPercentage)
                    {
                        // add the point to the list
                        matchingPointList.append(MatchingPoint(QPoint(loc.x, loc.y), value, sourceIndex));

                        // if we are only looking for a single target, we have found it, so we
                        //  can return
                        if(maximumMatches <= 1)
                            break;
                    }
                    else
                        break; // skip the rest
                }
            }
            catch(const cv::Exception &e)
            {
                mError = OpenCVException;
                mErrorString = tr("OpenCV exception: %1").arg(e.what());

                return MatchingPointList();
            }

            ++sourceIndex;
        }

		return matchingPointList;
	}
コード例 #2
0
ファイル: FastMatchTemplate.cpp プロジェクト: cfmak/Pictogram
//=============================================================================
// Assumes that source image exists and numDownPyrs > 1, no ROIs for either
//  image, and both images have the same depth and number of channels
bool
CFastMatchTemplate::FastMatchTemplate( const Mat&      source,
                   const Mat&      target,
                   vector<Point>*  foundPointsList,
                   vector<double>* confidencesList,
                   int             matchPercentage,
                   bool            findMultipleTargets,
                   int             numMaxima,
                   int             numDownPyrs,
                   int             searchExpansion )
{    
    // make sure that the template image is smaller than the source
    if(target.size().width > source.size().width ||
        target.size().height > source.size().height)
    {
        printf( "\nSource image must be larger than target image.\n" );
        return false;
    }

    if(source.depth() != target.depth())
    {
        printf( "\nSource image and target image must have same depth.\n" );
        return false;
    }

    if(source.channels() != target.channels())
    {
        printf("%d %d\n",source.channels() , target.channels());
        printf("\nSource image and target image must have same number of channels.\n" );
        return false;
    }

    Size sourceSize = source.size();
    Size targetSize = target.size();

    // create copies of the images to modify
    Mat copyOfSource = source.clone();
    Mat copyOfTarget = target.clone();

    // down pyramid the images
    for(int ii = 0; ii < numDownPyrs; ii++)
    {
        // start with the source image
        sourceSize.width  = (sourceSize.width  + 1) / 2;
        sourceSize.height = (sourceSize.height + 1) / 2;

        Mat smallSource(sourceSize, source.type());
        pyrDown(copyOfSource, smallSource);

        // prepare for next loop, if any
        copyOfSource = smallSource.clone();

        // next, do the target
        targetSize.width  = (targetSize.width  + 1) / 2;
        targetSize.height = (targetSize.height + 1) / 2;

        Mat smallTarget(targetSize, target.type());
        pyrDown(copyOfTarget, smallTarget);

        // prepare for next loop, if any
        copyOfTarget = smallTarget.clone();
    }

    // perform the match on the shrunken images
    Size smallTargetSize = copyOfTarget.size();
    Size smallSourceSize = copyOfSource.size();

    Size resultSize;
    resultSize.width = smallSourceSize.width - smallTargetSize.width + 1;
    resultSize.height = smallSourceSize.height - smallTargetSize.height + 1;

    Mat result(resultSize, CV_32FC1);
    matchTemplate(copyOfSource, copyOfTarget, result, CV_TM_CCOEFF_NORMED);

    // find the top match locations
    Point* locations = NULL;
    MultipleMaxLoc(result, &locations, numMaxima);

    // search the large images at the returned locations
    sourceSize = source.size();
    targetSize = target.size();

    // create a copy of the source in order to adjust its ROI for searching
    for(int currMax = 0; currMax < numMaxima; currMax++)
    {
        // transform the point to its corresponding point in the larger image
        locations[currMax].x *= (int)pow(2.0f, numDownPyrs);
        locations[currMax].y *= (int)pow(2.0f, numDownPyrs);
        locations[currMax].x += targetSize.width / 2;
        locations[currMax].y += targetSize.height / 2;

        const Point& searchPoint = locations[currMax];

        // if we are searching for multiple targets and we have found a target or
        //  multiple targets, we don't want to search in the same location(s) again
        if(findMultipleTargets && !foundPointsList->empty())
        {
            bool thisTargetFound = false;

            int numPoints = foundPointsList->size();
            for(int currPoint = 0; currPoint < numPoints; currPoint++)
            {
                const Point& foundPoint = (*foundPointsList)[currPoint];
                if(abs(searchPoint.x - foundPoint.x) <= searchExpansion * 2 &&
                    abs(searchPoint.y - foundPoint.y) <= searchExpansion * 2)
                {
                    thisTargetFound = true;
                    break;
                }
            }

            // if the current target has been found, continue onto the next point
            if(thisTargetFound)
            {
                continue;
            }
        }

        // set the source image's ROI to slightly larger than the target image,
        //  centred at the current point
        Rect searchRoi;
        searchRoi.x = searchPoint.x - (target.size().width) / 2 - searchExpansion;
        searchRoi.y = searchPoint.y - (target.size().height) / 2 - searchExpansion;
        searchRoi.width = target.size().width + searchExpansion * 2;
        searchRoi.height = target.size().height + searchExpansion * 2;

        // make sure ROI doesn't extend outside of image
        if(searchRoi.x < 0)
        {
            searchRoi.x = 0;
        }

        if(searchRoi.y < 0)
        {
            searchRoi.y = 0;
        }

        if((searchRoi.x + searchRoi.width) > (sourceSize.width - 1))
        {
            int numPixelsOver
                = (searchRoi.x + searchRoi.width) - (sourceSize.width - 1);

            searchRoi.width -= numPixelsOver;
        }

        if((searchRoi.y + searchRoi.height) > (sourceSize.height - 1))
        {
            int numPixelsOver
                = (searchRoi.y + searchRoi.height) - (sourceSize.height - 1);

            searchRoi.height -= numPixelsOver;
        }

        Mat searchImage = Mat(source, searchRoi);

        // perform the search on the large images
        resultSize.width = searchRoi.width - target.size().width + 1;
        resultSize.height = searchRoi.height - target.size().height + 1;

        result = Mat(resultSize, CV_32FC1);
        matchTemplate(searchImage, target, result, CV_TM_CCOEFF_NORMED);

        // find the best match location
        double minValue, maxValue;
        Point minLoc, maxLoc;
        minMaxLoc(result, &minValue, &maxValue, &minLoc, &maxLoc);
        maxValue *= 100;

        // transform point back to original image
        maxLoc.x += searchRoi.x + target.size().width / 2;
        maxLoc.y += searchRoi.y + target.size().height / 2;

        if(maxValue >= matchPercentage)
        {
            // add the point to the list
            foundPointsList->push_back(maxLoc);
            confidencesList->push_back(maxValue);

            // if we are only looking for a single target, we have found it, so we
            //  can return
            if(!findMultipleTargets)
            {
                break;
            }
        }
    }

//    if(foundPointsList->empty())
//    {
//        printf( "\nTarget was not found to required confidence of %d.\n",
//            matchPercentage );
//    }

    delete [] locations;

    return true;
}