我正在做一个家庭作业,我们需要编写一个获取图像和内核的函数,并且我们必须计算2d空间卷积。 使用高斯内核,可以得到预期的结果(图像模糊),但是如果我改用例如边缘检测内核(taken from here),则会发现某些功能无法正常工作(图像变灰)。
我想问题可能是边界处理(应为零填充),但我不确定完全正确实施还是最后归一化。 有没有一种方法可以显示浮动图片(例如,浮动图片的一个像素的值为25000),因为如果我不使用规范化,我认为它总是以255(白色)为上限。
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
int main(int argc, char *argv[])
{
cv::Mat img = cv::imread("orig.jpg",0); // load image as grayscale
img.convertTo(img,CV_32FC1); // convert to float
cv::Mat_<float> output(img.rows,img.cols); // create new mat with same size as source image
output = 0;
// creating a kernel (here Gaussian blur)
cv::Mat_<float> kernel(5,5);
kernel << 1,4,6,4,1,4,16,24,16,4,6,24,36,24,6,4,16,24,16,4,1,4,6,4,1;
int kCenterX = kernel.cols/2;
int kCenterY = kernel.rows/2;
for (int i = 0; i < img.rows; i++){ // for every row in image
for (int j = 0; j < img.cols; j++){ // for every column in image
for (int m = 0; m < kernel.rows; m++){ // for every row of kernel
int mm = kernel.rows - 1 -m; // row index of flipped kernel
for (int n = 0; n < kernel.cols; n++){ // for every column of kernel
int nn = kernel.cols - 1 -n; // column index of flipped kernel
// index for border handling
int ii = i + (m - kCenterY);
int jj = j + (n - kCenterX);
// checking if sample is still in bound of input image
// and if not, treat those pixels as 0 (because they won't get added to sum)
if (ii >= 0 && ii < img.rows && jj >= 0 && jj < img.cols)
output.at<float>(i,j) += img.at<float>(ii,jj) * kernel.at<float>(mm,nn);
}
}
}
}
// normalize input and output image (might be wrong, but I don't know how else I can see float images
cv::normalize(output, output, 0, 1, cv::NORM_MINMAX);
cv::normalize(img, img, 0, 1, cv::NORM_MINMAX);
// display images
cv::imshow("Original", img);
cv::imshow("Convolution", output);
cv::waitKey(0);
return 0;
}