实现思路:多个通道拆分,每个通道单独匹配。
对于每个通道,首先分别拉成一条,并按升序排序同时记下原编号,排序后每个像素比对,待匹配像素值不等于标准像素的,直接将待匹配对应位置像素更改为标准像素值。
实现效果:
标准影像 | |
待匹配影像 | |
匹配结果 |
代码:
依赖:
opencv_core
opencv_highgui
opencv_imgproc
opencv_imgcodecs
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <vector>
#include <algorithm>
struct FloatSort
{
int index;
float value;
};
bool compare(FloatSort a, FloatSort b)
{
return a.value < b.value;
}
cv::Mat CHistMatch(const cv::Mat img1, const cv::Mat img2)
{
/// @brief img2到img1,单通道
/// @param img1 第一张影像
/// @param img2 第二张影像
/// @return
cv::Mat mimg1 = img1.clone();
cv::Mat mimg2 = img2.clone();
//变换数据类型
mimg1.convertTo(mimg1, CV_32FC1);
mimg2.convertTo(mimg2, CV_32FC1);
//变形
mimg1 = mimg1.reshape(1, mimg1.rows * mimg1.cols);
mimg2 = mimg2.reshape(1, mimg2.rows * mimg2.cols);
//排序并记下序号
std::vector<FloatSort> mmimg1(mimg1.rows), mmimg2(mimg2.rows);
for (size_t i = 0; i < mmimg1.size(); i++)
{
mmimg1[i].index = i;
mmimg1[i].value = mimg1.at<float>(i, 0);
mmimg2[i].index = i;
mmimg2[i].value = mimg2.at<float>(i, 0);
}
sort(mmimg1.begin(), mmimg1.end(), compare);
sort(mmimg2.begin(), mmimg2.end(), compare);
//根据排序结果进行映射
for (size_t i = 0; i < mmimg1.size(); i++)
{
float num1 = mmimg1[i].value;
float num2 = mmimg2[i].value;
if (num1 != num2)
{
mimg2.at<float>(mmimg2[i].index, 0) = num1;
}
}
//变换并返回
cv::Mat nimg2 = cv::Mat(img2.rows, img2.cols, img2.type());
mimg2.reshape(1, img2.rows).convertTo(nimg2, img2.type());
return nimg2;
}
bool CHistMatch(const cv::Mat img1, const cv::Mat img2, cv::Mat &nimg)
{
/// @brief img2到img1,任意通道,但必须一致
/// @param img1 第一张影像
/// @param img2 第二张影像
/// @return
if (img1.channels() != img2.channels())
{
printf("通道不一致!!!");
return false;
}
if (img1.size() != img2.size())
{
printf("大小不一致!!!");
return false;
}
std::vector<cv::Mat> img1s, img2s, nimgs;
cv::split(img1, img1s);
cv::split(img2, img2s);
for (int i(0); i < img1s.size(); ++i)
{
cv::Mat img = CHistMatch(img1s[i], img2s[i]);
nimgs.push_back(img);
}
cv::merge(nimgs, nimg);
return true;
}
int main()
{
//读
cv::Mat img1 = cv::imread("data/img1.jpg");
cv::Mat img2 = cv::imread("data/img2.jpg");
//做
cv::Mat nimg2;
CHistMatch(img1, img2, nimg2);
//显
/*cv::namedWindow("img1", 0);
cv::namedWindow("img2", 0);
cv::namedWindow("nimg2", 0);
cv::imshow("img1", img1);
cv::imshow("img2", img2);
cv::imshow("nimg2", nimg2);
cv::waitKey();*/
//存
cv::imwrite("data/nimg2.jpg", nimg2);
}