You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

282 lines
5.4 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "stdafx.h"
#include "fuseImg.h"
#include "waveDecompose.h"
#include "waveReconstruct.h"
// 直方图投影
#include "histProject.h"
#include <omp.h>
// 功能:函数 FuseImg() 融合两幅输入图像
bool FuseImg(cv::Mat &dst, const cv::Mat img1, const cv::Mat img2, const string wname, const unsigned int level)
{
// 输入有效性判断
if (img1.empty() == true || (img1.type() != CV_8UC1 && img1.type() != CV_8UC3))
{
return false;
}
if (img2.empty() == true || (img2.type() != CV_8UC1 && img2.type() != CV_8UC3))
{
return false;
}
if (img1.type() != img2.type()
|| img1.size != img2.size)
{
return false;
}
if (wname == "" || level < 1)
{
return false;
}
// 图像类型
int imgType = img1.type();
if (imgType == CV_8UC3)
{
// 提取img1的亮度分量
cv::Mat YCrCb1;
cv::cvtColor(img1, YCrCb1, cv::COLOR_BGR2YCrCb);
std::vector<cv::Mat> planes1;
cv::split(YCrCb1, planes1);
// 提取img2的亮度分量
cv::Mat YCrCb2;
cv::cvtColor(img2, YCrCb2, cv::COLOR_BGR2YCrCb);
std::vector<cv::Mat> planes2;
cv::split(YCrCb2, planes2);
// 融合两幅图像亮度分量
cv::Mat fusion_Y;
if (false == FuseImg(fusion_Y, planes1[0], planes2[0], wname, level))
{
return false;
}
else
{
planes1[0] = fusion_Y;
// 其余两个通道取平均
planes1[1] = (planes1[1] + planes2[1]) / 2;
planes1[2] = (planes1[2] + planes2[2]) / 2;
cv::merge(planes1, YCrCb1);
cv::cvtColor(YCrCb1, dst, cv::COLOR_YCrCb2BGR);
}
return true;
}
else
{
// 图像1 小波分解
std::deque<cv::Mat> coef1;
std::deque<cv::Vec2i> scf1;
// 图像2 小波分解
std::deque<cv::Mat> coef2;
std::deque<cv::Vec2i> scf2;
bool ret1 = true;
bool ret2 = true;
#pragma omp parallel sections
{
#pragma omp section
{
ret1 = waveDec2(coef1, scf1, img1, wname, level);
}
#pragma omp section
{
ret2 = waveDec2(coef2, scf2, img2, wname, level);
}
}
if (ret1 == false || ret2 == false)
{
return false;
}
// 小波系数融合
// 1低频:取均值
coef1[0] = (coef1[0] + coef2[1]) / 2;
// 2高频取绝对值较大者
// 理论依据:大的小波系数含有较多的能量
for (unsigned int m = 1; m < coef1.size(); m++)
{
int rows = coef1[m].rows;
int cols = coef1[m].cols;
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
if (abs(coef2[m].at<double>(i, j)) > abs(coef1[m].at<double>(i, j)))
{
coef1[m].at<double>(i, j) = coef2[m].at<double>(i, j);
}
}
}
}
// 图像重构
cv::Mat dst_double;
if (false == waveRec2(dst_double, coef1, scf1, wname, level))
{
return false;
}
// 类型转换
double minVal = 0;
double maxVal = 0;
cv::minMaxIdx(dst_double, &minVal, &maxVal);
cv::Mat preHP; // 直方图均衡化前的融合图像
// 压缩 减少信息损失
dst_double.convertTo(preHP, CV_8UC1, 255.0 / (maxVal - minVal), -minVal / (maxVal - minVal));
// 自适应直方图投影,提高图像对比度
SAHP(dst, preHP);
return true;
}
}
// 功能:函数 FuseImgRGBplusIR() 融合两幅输入图像
bool FuseImgRGBplusIR(cv::Mat &dst, const cv::Mat CCDimg, const cv::Mat IRimg, const string wname, const unsigned int level)
{
// 输入有效性判断
if (CCDimg.empty() == true || CCDimg.type() != CV_8UC3)
{
return false;
}
if (IRimg.empty() == true || (IRimg.type() != CV_8UC1 && IRimg.type() != CV_8UC3))
{
return false;
}
if (CCDimg.size != IRimg.size)
{
return false;
}
if (wname == "" || level < 1)
{
return false;
}
// 根据类型区分
if (IRimg.type() == CV_8UC3)
{
// 提取IRimg亮度分量
cv::Mat IR;
std::vector<cv::Mat> planesIR;
cv::split(IRimg, planesIR);
planesIR[0].copyTo(IR);
// 提取CCDimg亮度分量
cv::Mat YCrCb;
cv::cvtColor(CCDimg, YCrCb, cv::COLOR_BGR2YCrCb);
std::vector<cv::Mat> planesCCD;
cv::split(YCrCb, planesCCD);
// 融合两幅图像亮度分量
cv::Mat dst_Y;
if (!FuseImg(dst_Y, planesCCD[0], IR, wname, level))
{
return false;
}
// 重构图像
dst_Y.copyTo(planesCCD[0]);
cv::merge(planesCCD, YCrCb);
cv::cvtColor(YCrCb, dst, cv::COLOR_YCrCb2BGR);
}
else
{
// 提取CCDimg亮度分量
cv::Mat YCrCb;
cv::cvtColor(CCDimg, YCrCb, cv::COLOR_BGR2YCrCb);
std::vector<cv::Mat> planesCCD;
cv::split(YCrCb, planesCCD);
// 融合两幅图像亮度分量
cv::Mat dst_Y;
if (false == FuseImg(dst_Y, planesCCD[0], IRimg, wname, level))
{
return false;
}
// 重构图像
dst_Y.copyTo(planesCCD[0]);
cv::merge(planesCCD, YCrCb);
cv::cvtColor(YCrCb, dst, cv::COLOR_YCrCb2BGR);
}
return true;
}
// 功能:函数 FastFuseImgCCDplusIR() 快速融合两幅输入图像
bool FastFuseImgRGBplusIR(cv::Mat &dst, const cv::Mat CCDimg, const cv::Mat IRimg)
{
// 输入有效性判断
if (CCDimg.empty() == true || CCDimg.type() != CV_8UC3)
{
return false;
}
if (IRimg.empty() == true || (IRimg.type() != CV_8UC1 && IRimg.type() != CV_8UC3))
{
return false;
}
if (CCDimg.size != IRimg.size)
{
return false;
}
// 单通道红外图像
cv::Mat IR;
// 根据类型区分
if (IRimg.type() == CV_8UC3)
{
// 提取IRimg亮度分量
std::vector<cv::Mat> planesIR;
cv::split(IRimg, planesIR);
planesIR[0].copyTo(IR);
}
else
{
IR = IRimg;
}
// 提取CCDimg亮度分量
cv::Mat YCrCb;
cv::cvtColor(CCDimg, YCrCb, cv::COLOR_BGR2YCrCb);
std::vector<cv::Mat> planesCCD;
cv::split(YCrCb, planesCCD);
// 融合两幅图像亮度分量
cv::Mat dst_Y = 0.5 * planesCCD[0] + 0.5 * IR;
// 增强亮度分量
cv::Mat enchanceDstY;
SAHP(enchanceDstY, dst_Y);
// 重构图像
planesCCD[0] = enchanceDstY;
cv::merge(planesCCD, YCrCb);
cv::cvtColor(YCrCb, dst, cv::COLOR_YCrCb2BGR);
return true;
}