SearchDialog::SearchDialog(QWidget * parent) : QDialog(parent) { QWidget * searchContainer = new QWidget(this); resultContainer = new QWidget(this); QWidget * buttonsContainer = new QWidget(this); searchField = new QLineEdit(searchContainer); closeButton = new QPushButton("Close", buttonsContainer); searchButton = new QPushButton("Search", buttonsContainer); result1 = new QPushButton(resultContainer); result2 = new QPushButton("toto", resultContainer); result3 = new QPushButton(resultContainer); QHBoxLayout * layout2 = new QHBoxLayout; layout2->addWidget(new QLabel("Search :", searchContainer)); layout2->addWidget(searchField); searchContainer->setLayout(layout2); QHBoxLayout * layout3 = new QHBoxLayout; layout3->addStretch(0); layout3->addWidget(closeButton); layout3->addWidget(searchButton); buttonsContainer->setLayout(layout3); QVBoxLayout * layout4 = new QVBoxLayout; layout4->addWidget(new QLabel("Best results :", resultContainer)); layout4->addWidget(result1); layout4->addWidget(result2); layout4->addWidget(result3); resultContainer->setLayout(layout4); QVBoxLayout * layout1 = new QVBoxLayout; layout1->addWidget(searchContainer); layout1->addStretch(0); layout1->addWidget(resultContainer); layout1->addStretch(0); layout1->addWidget(buttonsContainer); setLayout(layout1); setWindowTitle("Find an image"); setFixedSize(400, 300); resultContainer->setVisible(false); connect(closeButton, SIGNAL(clicked()), this, SLOT(accept())); connect(searchButton, SIGNAL(clicked()), this, SLOT(searchImage())); connect(searchField, SIGNAL(returnPressed()), this, SLOT(searchImage())); }
int main(int argc, char * argv[]) { bool gray = false; unsigned int nrDMs = 0; unsigned int nrPeriods = 0; float minSNR = std::numeric_limits< float >::max(); float maxSNR = std::numeric_limits< float >::min(); float snrSpaceDim = 0.0f; float * snrSpace = 0; std::string outFilename; std::ifstream searchFile; isa::utils::ArgumentList args(argc, argv); try { gray = args.getSwitch("-gray"); outFilename = args.getSwitchArgument< std::string >("-output"); nrDMs = args.getSwitchArgument< unsigned int >("-dms"); nrPeriods = args.getSwitchArgument< unsigned int >("-periods"); } catch ( isa::utils::EmptyCommandLine & err ) { std::cerr << args.getName() << " [-gray] -output ... -dms ... -periods ... input" << std::endl; return 1; } catch ( std::exception & err ) { std::cerr << err.what() << std::endl; return 1; } snrSpace = new float [nrDMs * nrPeriods]; try { while ( true ) { searchFile.open(args.getFirst< std::string >()); while ( ! searchFile.eof() ) { std::string temp; unsigned int splitPoint = 0; unsigned int DM = 0; unsigned int period = 0; float snr = 0.0f; std::getline(searchFile, temp); if ( ! std::isdigit(temp[0]) ) { continue; } splitPoint = temp.find(" "); period = isa::utils::castToType< std::string, unsigned int >(temp.substr(0, splitPoint)); temp = temp.substr(splitPoint + 1); splitPoint = temp.find(" "); DM = isa::utils::castToType< std::string, unsigned int >(temp.substr(0, splitPoint)); temp = temp.substr(splitPoint + 1); splitPoint = temp.find(" "); snr = isa::utils::castToType< std::string, float >(temp); if ( snr > maxSNR ) { maxSNR = snr; } if ( snr < minSNR ) { minSNR = snr; } snrSpace[(period * nrDMs) + DM] = snr; } searchFile.close(); } } catch ( isa::utils::EmptyCommandLine & err ) { snrSpaceDim = maxSNR - minSNR; } cimg_library::CImg< unsigned char > searchImage; AstroData::Color * colorMap; if ( gray ) { searchImage = cimg_library::CImg< unsigned char >(nrDMs, nrPeriods, 1, 1); } else { searchImage = cimg_library::CImg< unsigned char >(nrDMs, nrPeriods, 1, 3); colorMap = AstroData::getColorMap(); } for ( unsigned int period = 0; period < nrPeriods; period++ ) { for ( unsigned int DM = 0; DM < nrDMs; DM++ ) { float snr = snrSpace[(period * nrDMs) + DM]; if ( gray ) { searchImage(DM, (nrPeriods - 1) - period, 0, 0) = 255 - static_cast< unsigned char >(((snr - minSNR) * 255.0) / snrSpaceDim); } else { searchImage(DM, (nrPeriods - 1) - period, 0, 0) = (colorMap[static_cast< unsigned int >(((snr - minSNR) * 256.0) / snrSpaceDim)]).getR(); searchImage(DM, (nrPeriods - 1) - period, 0, 1) = (colorMap[static_cast< unsigned int >(((snr - minSNR) * 256.0) / snrSpaceDim)]).getG(); searchImage(DM, (nrPeriods - 1) - period, 0, 2) = (colorMap[static_cast< unsigned int >(((snr - minSNR) * 256.0) / snrSpaceDim)]).getB(); } } } searchImage.save(outFilename.c_str()); delete [] snrSpace; return 0; }
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; }