#include "stdafx.h" #include "superResolutionImg.h" // openCV Library #include #include "opencv2/nonfree/features2d.hpp" using namespace cv; #include #include "fuseImg.h" #include "histProject.h" // 移除NN比率大于阈值的匹配 int ClearMatchByKnnRatio(std::vector> &matches, float ratio) { try { // 移除匹配的数目 int removedCount = 0; // 初始化迭代器 std::vector>::iterator DMatchIterator = matches.begin(); // 遍历所有匹配 for (; DMatchIterator != matches.end(); ++DMatchIterator) { // 如果识别到两个最近邻 if (DMatchIterator->size() > 1) { // 次近距离 if ((*DMatchIterator)[1].distance > 0) { if ((*DMatchIterator)[0].distance / (*DMatchIterator)[1].distance > ratio) { DMatchIterator->clear(); removedCount++; } } else { DMatchIterator->clear(); removedCount++; } } else // 不包括两个最近邻 { DMatchIterator->clear(); removedCount++; } } // end of for return removedCount; } catch(cv::Exception &e) { e.msg; return 0; } catch(...) { return 0; } } // 获取对称匹配 int GetSysmmetryMatch(std::vector &sysmMatches, const std::vector> &preMatches, const std::vector> &nextMatches) { try { sysmMatches.clear(); // 对称匹配数目 int sysmMatchNum = 0; // 遍历matches1的所有匹配 std::vector>::const_iterator preMatchesIterator = preMatches.begin(); for(; preMatchesIterator != preMatches.end(); preMatchesIterator++) { // 跳过被删除的匹配 if (preMatchesIterator->size() < 2) { continue; } // 遍历matches2的所有匹配 std::vector>::const_iterator nextMatchesIterator = nextMatches.begin(); for(; nextMatchesIterator != nextMatches.end(); nextMatchesIterator++) { // 跳过被删除的匹配 if (nextMatchesIterator->size() < 2) { continue; } if ((*preMatchesIterator)[0].queryIdx == (*nextMatchesIterator)[0].trainIdx && (*preMatchesIterator)[0].trainIdx == (*nextMatchesIterator)[0].queryIdx) { // 添加对称匹配 sysmMatches.push_back(cv::DMatch((*preMatchesIterator)[0].queryIdx, (*preMatchesIterator)[0].trainIdx, (*preMatchesIterator)[0].distance)); sysmMatchNum++; break; } } } // 返回对称匹配数目 return sysmMatchNum; } catch(cv::Exception &e) { e.msg; return 0; } catch(...) { return 0; } } // 基于【对极约束】条件下的优质匹配识别(用到RANSAC估计方法) bool GetRansacBaseMatch(std::vector &ransacMatches, std::vector &prePts, std::vector &nextPts, const std::vector &matches, const std::vector &preKeyPts, const std::vector &nextKeyPts) { try { // 输入判断 对极约束至少需要8个点对, if (matches.size() > preKeyPts.size() || matches.size() > nextKeyPts.size() || matches.size() < 12) { return false; } // 清理输出 ransacMatches.clear(); prePts.clear(); nextPts.clear(); // 转换KeyPoint类型到Point2f std::vector::const_iterator it = matches.begin(); for(; it != matches.end(); it++) { // 得到左边特征点的坐标 prePts.push_back(preKeyPts[it->queryIdx].pt); // 得到右边特征点的坐标 nextPts.push_back(nextKeyPts[it->trainIdx].pt); } // 基于RANSAC计算基础矩阵 std::vector inliers(prePts.size(), 0); cv::Mat fundementalMat; // 基础矩阵 fundementalMat = cv::findFundamentalMat(cv::Mat(prePts), // 输入匹配点集1 cv::Mat(nextPts), // 输入匹配点集2 inliers, // 输出匹配状态 outlier(0) inlier(1) CV_FM_RANSAC, // RANSAC方法 3.0, // 到极线的距离 0.99); // 置信概率 // 提取通过的匹配 std::vector::const_iterator itInliers = inliers.begin(); std::vector::const_iterator itMatches = matches.begin(); for (; itInliers != inliers.end(); ++itInliers,++itMatches) { if (*itInliers) // 有效匹配 { ransacMatches.push_back((*itMatches)); } } // 根据接收的匹配,重新计算基础矩阵:fundementalMat prePts.clear(); nextPts.clear(); std::vector::const_iterator itRansacMatches = ransacMatches.begin(); for(; itRansacMatches != ransacMatches.end(); ++itRansacMatches) { // 得到左边特征点的坐标 prePts.push_back(preKeyPts[itRansacMatches->queryIdx].pt); // 得到右边特征点的坐标 nextPts.push_back(nextKeyPts[itRansacMatches->trainIdx].pt); } return true; } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } } // 基于最小二乘计算仿射变换矩阵 bool GetAffineTransMat(cv::Mat &result, const std::vector &prePoints, const std::vector &nextPoints) { try { int preSize = prePoints.size(); int nextSize = nextPoints.size(); if (preSize < 3 || nextSize < 3 || preSize != nextSize) { return false; } // 重新分配输出矩阵 result.create(3, 3, CV_64FC1); result = cv::Scalar(0); // 匹配数目 int MatchNum = preSize; /* set up matrices so we can unstack homography into X; AX = B */ cv::Mat A(2 * MatchNum, 6, CV_64FC1); cv::Mat B(2 * MatchNum, 1, CV_64FC1); cv::Mat X(6, 1, CV_64FC1); // 置零 A = cv::Scalar(0); B = cv::Scalar(0); X = cv::Scalar(0); // 初始化矩阵 for(int i = 0; i < MatchNum; i++ ) { A.at(i, 0) = prePoints[i].x; A.at(i, 1) = prePoints[i].y; A.at(i, 2) = 1.0f; A.at(i + MatchNum, 3) = prePoints[i].x; A.at(i + MatchNum, 4) = prePoints[i].y; A.at(i + MatchNum, 5) = 1.0f; B.at(i, 0) = nextPoints[i].x; B.at(i + MatchNum, 0) = nextPoints[i].y; } // 解方程 cv::solve(A, B, X, CV_SVD); // 赋值 result.at(0, 0) = X.at(0, 0); result.at(0, 1) = X.at(1, 0); result.at(0, 2) = X.at(2, 0); result.at(1, 0) = X.at(3, 0); result.at(1, 1) = X.at(4, 0); result.at(1, 2) = X.at(5, 0); result.at(2, 0) = 0.0; result.at(2, 1) = 0.0; result.at(2, 2) = 1.0; return true; } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } } // 基于最小二乘计算透视变换矩阵 bool GetPerpectTransMat(cv::Mat &result, const std::vector &prePoints, const std::vector &nextPoints) { try { int preSize = prePoints.size(); int nextSize = nextPoints.size(); if (preSize < 4 || nextSize < 4 || preSize != nextSize) { return false; } // 重新分配输出矩阵 result.create(3, 3, CV_64FC1); result = cv::Scalar(0); // 匹配数目 int MatchNum = nextSize; /* set up matrices so we can unstack homography into X; AX = B */ cv::Mat A(2 * MatchNum, 8, CV_64FC1); cv::Mat B(2 * MatchNum, 1, CV_64FC1); cv::Mat X(8, 1, CV_64FC1); // 置零 A = cv::Scalar(0); B = cv::Scalar(0); X = cv::Scalar(0); // 初始化矩阵 for(int i = 0; i < MatchNum; i++ ) { A.at(i, 0) = prePoints[i].x; A.at(i, 1) = prePoints[i].y; A.at(i, 2) = 1.0f; A.at(i, 6) = -prePoints[i].x * nextPoints[i].x; A.at(i, 7) = -prePoints[i].y * nextPoints[i].x; A.at(i + MatchNum, 3) = prePoints[i].x; A.at(i + MatchNum, 4) = prePoints[i].y; A.at(i + MatchNum, 5) = 1.0f; A.at(i + MatchNum, 6) = -prePoints[i].x * nextPoints[i].y; A.at(i + MatchNum, 7) = -prePoints[i].y * nextPoints[i].y; B.at(i, 0) = nextPoints[i].x; B.at(i + MatchNum, 0) = nextPoints[i].y; } // 解方程 cv::solve(A, B, X, CV_SVD); // 赋值 result.at(0, 0) = X.at(0, 0); result.at(0, 1) = X.at(1, 0); result.at(0, 2) = X.at(2, 0); result.at(1, 0) = X.at(3, 0); result.at(1, 1) = X.at(4, 0); result.at(1, 2) = X.at(5, 0); result.at(2, 0) = X.at(6, 0); result.at(2, 1) = X.at(7, 0); result.at(2, 2) = 1.0; return true; } catch(cv::Exception &e) { e.msg; return false; } catch(...) { return false; } } // 相邻图像间特征匹配,并计算关系 void CalImgAdjacentMat(std::deque &adjacentMatDeque, std::deque &successTagDeque, const std::deque> &imgKeyptsDeque, const std::deque &imgDescriptorsDeque) { if (imgKeyptsDeque.empty() == true || imgDescriptorsDeque.empty() == true || imgKeyptsDeque.size() != imgDescriptorsDeque.size()) { return; } adjacentMatDeque.clear(); successTagDeque.clear(); // 总数目 size_t count = imgKeyptsDeque.size(); for (size_t i = 0; i < (count - 1); i++) { // Flann匹配器 cv::FlannBasedMatcher matcher; std::vector preImgKeypts = imgKeyptsDeque.at(i); std::vector nextImgKeypts = imgKeyptsDeque.at(i + 1); cv::Mat preImgDescriptors = imgDescriptorsDeque.at(i); cv::Mat nextImgDescriptors = imgDescriptorsDeque.at(i + 1); // 初步匹配结果 std::vector> Pre2NextMatches; std::vector> Next2PreMatches; // 最近邻/次近邻特征匹配 matcher.knnMatch(preImgDescriptors, nextImgDescriptors, Pre2NextMatches, 2); // 前向匹配 matcher.knnMatch(nextImgDescriptors, preImgDescriptors, Next2PreMatches, 2); // 后向匹配 // 剔除部分误匹配 ClearMatchByKnnRatio(Pre2NextMatches, 0.65f); ClearMatchByKnnRatio(Next2PreMatches, 0.65f); // 对称匹配 vector SysmMatches; GetSysmmetryMatch(SysmMatches, Pre2NextMatches, Next2PreMatches); // Ransac:对极约束提出误匹配 std::vector RansacMatches; std::vector PrePoints; std::vector NextPoints; bool MatchResult = false; MatchResult = GetRansacBaseMatch(RansacMatches, // Ransac匹配 PrePoints, NextPoints, SysmMatches, // 对称匹配 preImgKeypts, nextImgKeypts); if (MatchResult == false) { adjacentMatDeque.push_back(cv::Mat()); successTagDeque.push_back(0); continue; } // 两帧图像的连接矩阵 bool TransResult = false; cv::Mat AdjacentMat; TransResult = GetPerpectTransMat(AdjacentMat, PrePoints, NextPoints); if (TransResult == false) { adjacentMatDeque.push_back(cv::Mat()); successTagDeque.push_back(0); continue; } else { adjacentMatDeque.push_back(AdjacentMat); successTagDeque.push_back(1); } } } // 灰度图像(红外图像)超分辨率构建 int SuperResolutionImg(cv::Mat &dst, const std::deque &imgDeque, double multiple) { if (imgDeque.size() < 2) { return 0; } // 超分倍数 if (multiple < 1) { multiple = 1; } else if (multiple > 2) { multiple = 2; } // 基准 第0张图像 cv::Size imgSize = imgDeque[0].size(); for (size_t i = 0; i < imgDeque.size(); i++) { if (imgDeque[i].type() != CV_8UC1 || imgDeque[i].size() != imgSize) // 尺寸和类型判断 { return 0; } } // 图像增大一倍后的集合 std::deque imgUpSampleDeque; for (size_t i = 0; i < imgDeque.size(); i++) { // 尺寸加倍 cv::Mat upSampleImg; cv::resize(imgDeque.at(i), upSampleImg, cv::Size(int(imgDeque.at(i).cols * multiple), int(imgDeque.at(i).rows * multiple)), 0, 0, 1); imgUpSampleDeque.push_back(upSampleImg); } // 特征集合 std::deque> imgKeyptsDeque; std::deque imgDescriptorsDeque; cv::SIFT sift(0, 3, 0.004); // 小阈值 for (size_t i = 0; i < imgUpSampleDeque.size(); i++) { // 计算特征点 特征向量 std::vector imgKeypts; cv::Mat imgDescriptors; sift(imgUpSampleDeque.at(i), noArray(), imgKeypts, imgDescriptors, false); // 保存 imgKeyptsDeque.push_back(imgKeypts); imgDescriptorsDeque.push_back(imgDescriptors); } // 图像特征匹配 std::deque adjacentMatDeque; std::deque successTagDeque; CalImgAdjacentMat(adjacentMatDeque, successTagDeque, imgKeyptsDeque, imgDescriptorsDeque); // 选出最佳的一段数据 std::deque segment; for (size_t i = 0; i < successTagDeque.size(); i++) { int count = 0; for (size_t t = i; t < successTagDeque.size(); t++) { if (successTagDeque.at(t) == 1) { count++; } else { break; } } segment.push_back(count); } // 找出最大值及其位置 std::deque segmentCopy = segment; std::sort(segmentCopy.begin(), segmentCopy.end()); int maxVal = segmentCopy.at(segmentCopy.size() - 1); // 最少3张图像 if (maxVal < 2) { return 0; } int location = 0; // 位置 for (size_t i = 0; i < segment.size(); i++) { if (maxVal == segment.at(i)) { location = i; break; } } // 融合全部数据 if (maxVal == static_cast(successTagDeque.size())) { // 图像细节增强 for (size_t i = 0; i < imgUpSampleDeque.size(); i++) { cv::Mat img; imgUpSampleDeque[i].copyTo(img); GNRHP(img, imgUpSampleDeque[i]); } // 逐步融合 for (int i = imgUpSampleDeque.size() - 2; i > -1; i--) { cv::Mat img_pre = imgUpSampleDeque[i]; cv::Mat img_next = imgUpSampleDeque[i+1]; cv::Mat img_preNext; img_pre.copyTo(img_preNext); // 两帧图像的连接矩阵 cv::Mat m_AdjacentMat = adjacentMatDeque[i]; // 生成next 替换 pre 图像 double a00 = m_AdjacentMat.at(0, 0); double a01 = m_AdjacentMat.at(0, 1); double a02 = m_AdjacentMat.at(0, 2); double a10 = m_AdjacentMat.at(1, 0); double a11 = m_AdjacentMat.at(1, 1); double a12 = m_AdjacentMat.at(1, 2); double a20 = m_AdjacentMat.at(2, 0); double a21 = m_AdjacentMat.at(2, 1); double a22 = m_AdjacentMat.at(2, 2); for(int r = 0; r < img_preNext.rows; r++) { // #pragma omp parallel for for (int c = 0; c < img_preNext.cols; c++) { double denominator = c * a20 + r * a21 + a22; double src_x = (c * a00 + r * a01 + a02) / denominator; double src_y = (c * a10 + r * a11 + a12) / denominator; // 最近邻,速度快 int x_nearest = int(src_x + 0.5); int y_nearest = int(src_y + 0.5); if ( x_nearest >= 0 && y_nearest >= 0 && x_nearest < img_next.cols && y_nearest < img_next.rows) { img_preNext.at(r, c) = img_next.at(y_nearest, x_nearest); } } } // 搬移像素结束 // 融合 img_pre 和 img_preNext cv::Mat fusion; FuseImg(fusion, img_pre, img_preNext, "sym4", 10); // 用 fusion 替换 validImgUpSampleDeque[i] fusion.copyTo(imgUpSampleDeque[i]); } imgUpSampleDeque[0].copyTo(dst); return imgUpSampleDeque.size(); } else { // 选出有效的图像片段 std::deque validImgUpSampleDeque(imgUpSampleDeque.begin() + location, imgUpSampleDeque.begin() + location + maxVal + 1); // 图像细节增强 for (size_t i = 0; i < validImgUpSampleDeque.size(); i++) { cv::Mat img; validImgUpSampleDeque[i].copyTo(img); GNRHP(img, validImgUpSampleDeque[i]); } std::deque validAdjacentMatDeque(adjacentMatDeque.begin() + location, adjacentMatDeque.begin() + location + maxVal); imgUpSampleDeque.clear(); adjacentMatDeque.clear(); // 逐步融合 for (int i = validImgUpSampleDeque.size() - 2; i > -1; i--) { cv::Mat img_pre = validImgUpSampleDeque[i]; cv::Mat img_next = validImgUpSampleDeque[i+1]; cv::Mat img_preNext; img_pre.copyTo(img_preNext); // 两帧图像的连接矩阵 cv::Mat m_AdjacentMat = validAdjacentMatDeque[i]; // 生成next 替换 pre 图像 double a00 = m_AdjacentMat.at(0, 0); double a01 = m_AdjacentMat.at(0, 1); double a02 = m_AdjacentMat.at(0, 2); double a10 = m_AdjacentMat.at(1, 0); double a11 = m_AdjacentMat.at(1, 1); double a12 = m_AdjacentMat.at(1, 2); double a20 = m_AdjacentMat.at(2, 0); double a21 = m_AdjacentMat.at(2, 1); double a22 = m_AdjacentMat.at(2, 2); for(int r = 0; r < img_preNext.rows; r++) { // #pragma omp parallel for for (int c = 0; c < img_preNext.cols; c++) { double denominator = c * a20 + r * a21 + a22; double src_x = (c * a00 + r * a01 + a02) / denominator; double src_y = (c * a10 + r * a11 + a12) / denominator; // 最近邻,速度快 int x_nearest = int(src_x + 0.5); int y_nearest = int(src_y + 0.5); if ( x_nearest >= 0 && y_nearest >= 0 && x_nearest < img_next.cols && y_nearest < img_next.rows) { img_preNext.at(r, c) = img_next.at(y_nearest, x_nearest); } } } // 搬移像素结束 // 融合 img_pre 和 img_preNext cv::Mat fusion; FuseImg(fusion, img_pre, img_preNext, "sym4", 10); // 用 fusion 替换 validImgUpSampleDeque[i] fusion.copyTo(validImgUpSampleDeque[i]); } validImgUpSampleDeque[0].copyTo(dst); return validImgUpSampleDeque.size(); } }