opencv之傅里叶变换

1. 图像掩码操作

 图像掩码操作是通过掩码算子重新计算图像中各个像素的值;掩码核算子刻画邻域像素点对新像素值得影响程度;

1.1 基于像素邻域遍历

cv::Mat MyFilter2D(cv::Mat srcImage)
{
	const int nChannels = srcImage.channels();

	cv::Mat resultImage(Size(srcImage.rows,srcImage.cols),srcImage.type());
	for(int i = 1; i < srcImage.rows - 1; i++){
		//获取邻域指针
		const uchar *previous = srcImage.ptr(i-1);
		const uchar *current = srcImage.ptr(i);
		const uchar *next = srcImage.ptr(i+1);
	
		uchar *output = resultImage.ptr(i);

		for(int j = nChannels; j < nChannels*(srcImage.cols-1); j++){
			*output++ = saturate_cast((current[j-nChannels] + current[j+nChannels] + previous[j] + next[j])/4);
		}
	}

	//边界处理
	resultImage.row(0).setTo(Scalar(0));
	resultImage.row(resultImage.rows-1).setTo(Scalar(0));
	resultImage.col(0).setTo(Scalar(0));
	resultImage.col(resultImage.cols-1).setTo(Scalar(0));

	return resultImage;
}

1.2 基于filter2D函数

cv::Mat filter2D_(cv::Mat srcImage)
{
	cv::Mat resultImage(Size(srcImage.rows,srcImage.cols),srcImage.type());

	Mat kern = (Mat_(3,3) << 0,1,0,1,0,1,0,1,0) / (float)(4);
	filter2D(srcImage, resultImage, srcImage.depth(), kern);

	return resultImage;
}

2. 离散傅里叶

将时域信号分解为不同频率的正弦信号或余弦信号叠加和;

cv::Mat DFT(cv::Mat srcImage)
{
	cv::Mat srcGray;
	cvtColor(srcImage, srcGray, CV_RGB2GRAY);

	//将输入图像延扩到最佳的尺寸;
	int nRows = getOptimalDFTSize(srcGray.rows);
	int nCols = getOptimalDFTSize(srcGray.cols);

	cv::Mat resultImage;
	//把灰度图像放在左上角,向右边和下边扩展图像,把添加的像素初始化为0;
	copyMakeBorder(srcGray, resultImage, 0, nRows-srcGray.rows, 0, nCols-srcGray.cols, BORDER_CONSTANT, Scalar::all(0));

	//为傅里叶变换的结果(实部和虚部)分配存储空间;
	cv::Mat planes[] = {
		cv::Mat_(resultImage),
		cv::Mat::zeros(Size(resultImage.rows,resultImage.cols), CV_32F)
	};

	cv::Mat completeI;
	//为延扩后的图像增添一个初始化为0的通道;
	merge(planes, 2, completeI);

	//进行离散傅里叶变换
	dft(completeI, completeI);

	//将复数转换为幅度
	split(completeI, planes);
	magnitude(planes[0], planes[1], planes[0]);

	cv::Mat dftResultImage = planes[0];

	//对数尺度缩放
	dftResultImage += 1;
	log(dftResultImage, dftResultImage);

	//剪切和重分布幅度图象限;
	dftResultImage = dftResultImage(Rect(0,0,srcGray.cols,srcImage.rows));

	//归一化图像
	normalize(dftResultImage, dftResultImage, 0, 1, CV_MINMAX);

	int cx = dftResultImage.cols / 2;
	int cy = dftResultImage.rows / 2;

	cv::Mat tmp;
	//为每一个象限创建ROI
	Mat q0(dftResultImage, Rect(0,0,cx,cy));
	Mat q1(dftResultImage, Rect(cx,0,cx,cy));
	Mat q2(dftResultImage, Rect(0,cy,cx,cy));
	Mat q3(dftResultImage, Rect(cx,cy,cx,cy));

	//交换象限
	q0.copyTo(tmp);
	q3.copyTo(q0);
	tmp.copyTo(q3);

	q1.copyTo(tmp);
	q2.copyTo(q1);
	tmp.copyTo(q2);

	return dftResultImage;
}

3. 图像卷积

void convolution(cv::Mat src, cv::Mat kernel, cv::Mat &dst)
{
	//输出图像定义
	dst.create(abs(src.rows-kernel.rows)+1, abs(src.cols-kernel.cols)+1, src.type());

	cv::Size dftSize;
	//计算傅里叶变换尺寸
	dftSize.width = getOptimalDFTSize(src.cols+kernel.cols-1);
	dftSize.height= getOptimalDFTSize(src.rows+kernel.rows-1);

	//创建临时图像,初始化为0
	cv::Mat tempA(dftSize, src.type(), Scalar::all(0));
	cv::Mat tempB(dftSize, kernel.type(), Scalar::all(0));

	//对区域进行复制
	cv::Mat roiA(tempA, Rect(0,0,src.cols,src.rows));
	src.copyTo(roiA);

	cv::Mat roiB(tempB, Rect(0,0,kernel.cols,kernel.rows));
	kernel.copyTo(roiB);

	//傅里叶变换
	dft(tempA, tempA, 0, src.rows);
	dft(tempB, tempB, 0, kernel.rows);

	//对频谱中的每个元素进行乘法操作
	mulSpectrums(tempA, tempB, tempA, DFT_COMPLEX_OUTPUT);

	//变换结果,所有行非0
	dft(tempA,tempA,DFT_INVERSE+DFT_SCALE, dst.rows);

	//复制结果到输出图像
	tempA(Rect(0,0,dst.cols,dst.rows)).copyTo(dst);
}

 

你可能感兴趣的:(#,opencv,opencv)