c++直方图匹配终极版,支持任意通道数(opencv版本)

实现思路:多个通道拆分,每个通道单独匹配。

对于每个通道,首先分别拉成一条,并按升序排序同时记下原编号,排序后每个像素比对,待匹配像素值不等于标准像素的,直接将待匹配对应位置像素更改为标准像素值。

实现效果

标准影像
待匹配影像
匹配结果

 代码

依赖:

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);
}

 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值