I'm trying some smoothing filter. I don't want to use the OpenCV filter function ( yes, I know it exists, but for didactical use I want to create mine). If you run my code, you will see that the output Mat will be stretched. I'm new in OpenCV and I'm not able to understand what happen. In my code, I add border to the original picture, so I can apply a filter 3x3 without stackoverflow problem.
#include <opencv2/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <opencv2/imgproc/imgproc.hpp>
/*
Smoothing Median
*/
using namespace cv;
using namespace std;
int main()
{
const int sizeFilter = 3;
const int border = 2;
Mat averageFilter(sizeFilter, sizeFilter, CV_8U, 1);
Mat input = imread("lena.jpg");
Mat sizedInput;
sizedInput = input.clone();
int sizeX = input.rows;
int sizeY = input.cols;
namedWindow("sizedInput");
imshow("sizedInput", sizedInput);
// Aggiungo i bordi per filtrare
copyMakeBorder(input, sizedInput, border, border,
border, border, BORDER_REPLICATE);
Mat dst = Mat(sizeX, sizeY, CV_8U);
for (int x = 2; x < sizeX; x++) {
for (int y = 2; y < sizeY; y++) {
int sum = 0;
sum = (int)sizedInput.at<uchar>(x - 1, y - 1)
+ (int)sizedInput.at<uchar>(x - 1, y)
+ (int)sizedInput.at<uchar>(x , y - 1)
+ (int)sizedInput.at<uchar>(x, y)
+ (int)sizedInput.at<uchar>(x, y + 1)
+ (int)sizedInput.at<uchar>(x + 1, y - 1)
+ (int)sizedInput.at<uchar>(x + 1, y + 1);
sum = sum * (0.11);
dst.at<uchar>(x , y) = sum;
}
}
namedWindow("Blu");
imshow("Blu", dst);
waitKey();
return 0;
}
You are working as if the image was grayscale (.at<uchar>
), but you're loading the image as a color image.
In this way you basically read only one third of the image pixels. Color images are stored as a sequence: BGRBGRBGR...
, while grayscale images as: XXXXXXXXX...
(X for gray). For example, if you read the second grayscale value, you're effectively reading the first green value:
bytes: 0 1 2 3 4 5 6 7 8 ...
B G R B G R B G R ...
X X X X X X X X X ...
^
The resulting image would appear as stretched by a factor of 3 in horizontal.
Load the image directly in grayscale:
Mat input = imread("lena.jpg", IMREAD_GRAYSCALE);
or convert after loading:
Mat input = imread("lena.jpg");
cvtColor(input, input, BGR2GRAY).
Aside, pay attention that you're using a confusing naming convention. x should be referred to columns, and y to rows.