#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 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_(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 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 &mats, bool isTwoSide) { (void)isTwoSide; //for (cv::Mat& var : mats) for (int i = 0;i < mats.size();i++) apply(mats[i], 0); }