Reputation: 15
I want to create a dilation image using a kernel that runs through the entire image and checks if the kernel zone has 0, if so, it gives the new image a pixel of 255. My code is giving me an all black dst and I don't know why. This is the code:
Mat vcpi_binary_dilate(Mat src)
{
if (src.empty())
{
cout << "Failed to load image.";
return src;
}
Mat dst(src.rows, src.cols, CV_8UC1, Scalar(0));
const int kernnel = 3;
int array[kernnel * kernnel] = {};
for (int y = kernnel / 2; y < src.cols - kernnel / 2; y++)
{
for (int x = kernnel / 2; x < src.rows - kernnel / 2; x++)
for (int yk = -kernnel / 2; yk <= kernnel / 2; yk++)
{
for (int xk = -kernnel / 2; xk <= kernnel / 2; xk++)
{
if (src.at<uchar>(y + yk, x + xk) == 0)
{
dst.at<uchar>(y + yk, x + xk) = 255;
}
}
}
}
imshow("Image ", src);
imshow("Image dilate", dst);
waitKey(0);
return dst;
}
I hope to have an output image of this type.
Upvotes: 0
Views: 215
Reputation: 28074
I am not sure about the algorithm you are trying to implement.
But there is one thing that is definately wrong:
The image dimensions are mixed up-
cols
is the width and corresponds to the x
axis.
rows
is the height and corresponds to the y
axis.
This is causing you to access the images using cv::Mat::at
with invalid coordinates.
Therefore you need to change:
for (int y = kernnel / 2; y < src.cols - kernnel / 2; y++)
{
for (int x = kernnel / 2; x < src.rows - kernnel / 2; x++)
{
To:
//--------------------------------vvvv--------------------
for (int y = kernnel / 2; y < src.rows - kernnel / 2; y++)
{
//------------------------------------vvvv--------------------
for (int x = kernnel / 2; x < src.cols - kernnel / 2; x++)
{
Note that this is consistent with your calls ...at<uchar>(y + yk, x + xk)
, since cv::Mat::at
expects the row
(i.e. y
coordinate) first.
A side note: Why is "using namespace std;" considered bad practice?.
Edit:
After having a look at the matlab code in your comment, which applies an algorithm different than what you described in your question, you'll need to do the following changes:
im2bw
.dst
current pixel, not the one in the neighborhood.Maybe something like:
cv::Mat vcpi_binary_dilate(cv::Mat src) {
if (src.empty()) {
std::cout << "Failed to load image.";
return src;
}
cv::threshold(src, src, 127, 255, CV_THRESH_BINARY);
cv::Mat dst(src.rows, src.cols, CV_8UC1, cv::Scalar(255)); // <-- Replacement for im2bw, might need tuning.
const int kernnel = 3;
int array[kernnel * kernnel] = {};
for (int y = kernnel / 2; y < src.rows - kernnel / 2; y++)
{
for (int x = kernnel / 2; x < src.cols - kernnel / 2; x++)
{
for (int yk = -kernnel / 2; yk <= kernnel / 2; yk++)
{
for (int xk = -kernnel / 2; xk <= kernnel / 2; xk++)
{
if (src.at<uchar>(y + yk, x + xk) == 0) {
dst.at<uchar>(y, x) = 0; // <-- Update the current pixel, not the one in the neighborhood.
}
}
}
}
}
cv::imshow("Image ", src);
cv::imshow("Image dilate", dst);
cv::waitKey(0);
return dst;
}
Upvotes: 1