图像掩码操作是通过掩码算子重新计算图像中各个像素的值;掩码核算子刻画邻域像素点对新像素值得影响程度;
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;
}
将时域信号分解为不同频率的正弦信号或余弦信号叠加和;
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;
}
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);
}