huago-corrcet_tools/HuaGoCorrect/ImageApplyTextureRemoval.cpp

166 lines
4.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "ImageApplyTextureRemoval.h"
//交换对角线
void zero_to_center(cv::Mat& image, int colToCut, int rowToCut)
{
cv::Mat q1(image, cv::Rect(0, 0, colToCut, rowToCut));
cv::Mat q2(image, cv::Rect(colToCut, 0, colToCut, rowToCut));
cv::Mat q3(image, cv::Rect(0, rowToCut, colToCut, rowToCut));
cv::Mat q4(image, cv::Rect(colToCut, rowToCut, colToCut, rowToCut));
//第二象限和第四象限进行交换
cv::Mat tmpImg;
q1.copyTo(tmpImg);
q4.copyTo(q1);
tmpImg.copyTo(q4);
//第一象限和第三象限进行交换
q2.copyTo(tmpImg);
q3.copyTo(q2);
tmpImg.copyTo(q3);
}
//创建光谱
cv::Mat create_spectrum(cv::Mat* matArray)
{
cv::Mat dst;
cv::magnitude(matArray[0], matArray[1], dst);
#if 1
cv::divide(dst, dst.cols * dst.rows, dst);
#else
dst += Scalar::all(1);
log(dst, dst);
normalize(dst, dst, 1, 0, CV_MINMAX);
#endif
#if 0
imshow("频谱", dst);
#endif
return dst;
}
//反傅里叶变换
void inverseFourierTransform(const cv::Mat& src, cv::Mat& dst)
{
cv::Mat complexIDFT;
cv::Mat matArray[2];
cv::idft(src, complexIDFT);
cv::split(complexIDFT, matArray);
cv::magnitude(matArray[0], matArray[1], dst);
cv::normalize(dst, dst, 0, 1, CV_MINMAX);
}
//制作陷波滤波器
cv::Mat createFilter(const cv::Mat& spectrum, int dilateSize, int erodeSize)
{
cv::Mat temp;
spectrum.convertTo(temp, CV_8UC1, 255);
cv::threshold(temp, temp, 0, 255, CV_THRESH_OTSU);
//imshow("二值化", temp);
cv::Mat element1 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(dilateSize, dilateSize));
cv::Mat element2 = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(erodeSize, erodeSize));
cv::dilate(temp, temp, element1);
cv::erode(temp, temp, element2);
cv::floodFill(temp, cv::Point(temp.cols / 2, temp.rows / 2), cv::Scalar(0)); //漫水填充中心区域
//cv::imshow("二值化", temp);
cv::medianBlur(~temp, temp, 5); //中值滤波
//陷波滤波器复制
cv::Mat filter;
temp.convertTo(filter, CV_32FC1);
cv::normalize(filter, filter, 1, 0, CV_MINMAX);
std::vector<cv::Mat> mv;
mv.push_back(filter);
mv.push_back(filter);
cv::merge(mv, filter);
return filter;
}
void CImageApplyTextureRemoval::textureRemovalGray(cv::Mat& img)
{
//得到DFT的最佳尺寸2的指数以加速计算
cv::Mat paddedImg;
int m = cv::getOptimalDFTSize(img.rows);
int n = cv::getOptimalDFTSize(img.cols);
//填充图像的下端和右端
cv::copyMakeBorder(img, paddedImg, 0, m - img.rows, 0, n - img.cols,
cv::BORDER_CONSTANT, cv::Scalar::all(0));
//将填充的图像组成一个复数的二维数组两个通道的Mat用于DFT
cv::Mat matArray[] = { cv::Mat_<float>(paddedImg), cv::Mat::zeros(paddedImg.size(), CV_32F) };
cv::Mat complexInput, complexOutput;
cv::merge(matArray, 2, complexInput);
cv::dft(complexInput, complexOutput);
cv::split(complexOutput, matArray); //计算幅度谱(傅里叶谱)
//滤波
//将实部和虚部按照频谱图的方式换位
//低频在图像中心,用于滤波
zero_to_center(matArray[0], complexOutput.cols / 2, complexOutput.rows / 2);
zero_to_center(matArray[1], complexOutput.cols / 2, complexOutput.rows / 2);
cv::Mat spectrum = create_spectrum(matArray);
//创建滤波器
cv::Mat filter = createFilter(spectrum, m_dilateSize, m_erodeSize);
cv::merge(matArray, 2, complexOutput);
cv::multiply(complexOutput, filter, filter);
//IDFT得到滤波结果
cv::Size imgSize = img.size();
inverseFourierTransform(filter, img);
img = img(cv::Rect(cv::Point(0, 0), imgSize));
img *= 255;
img.convertTo(img, CV_8UC1);
}
CImageApplyTextureRemoval::CImageApplyTextureRemoval()
: CImageApply()
, m_dilateSize(11)
, m_erodeSize(7)
{
}
CImageApplyTextureRemoval::CImageApplyTextureRemoval(int dilateSize, int erodeSize)
: CImageApply()
, m_dilateSize(dilateSize)
, m_erodeSize(erodeSize)
{
}
CImageApplyTextureRemoval::~CImageApplyTextureRemoval()
{
}
void CImageApplyTextureRemoval::apply(cv::Mat &pDib, int side)
{
(void)side;
if (pDib.channels() == 1)
textureRemovalGray(pDib);
else
{
std::vector<cv::Mat> rgb(3);
cv::split(pDib, rgb);
for (int i = 0;i < rgb.size();i++)
//for (cv::Mat& var : rgb)
textureRemovalGray(rgb[i]);
cv::merge(rgb, pDib);
}
}
void CImageApplyTextureRemoval::apply(std::vector<cv::Mat> &mats, bool isTwoSide)
{
(void)isTwoSide;
//for (cv::Mat& var : mats)
for (int i = 0;i < mats.size();i++)
apply(mats[i], 0);
}