Sobel Edge Detection C++ Code (with CImg)


Following from my prior page of code (here) we now need to use that code, making the "DoubleToInteger" function public, and we implement the Sobel operation...

Find the full post here: http://megalomaniacbore.blogspot.co.uk/2012/04/image-processing-in-c.html
==== SobelHelpers.h ====

#ifndef SOBEL_HELPERS_HEADER
#define SOBEL_HELPERS_HEADER

#include "Types.h"

namespace Xelous
{

class SobelHelper
{
private:

///<Summary>
/// The mask to utilise for Gy
///</Summary>
static const int c_YMask[];

///<Summary>
/// The mask to utilise for the Gx
///</Summary>
static const int c_XMask[];

public:

///<Summary>
/// Function to carry out the sobel
/// operation, it is recommended the
/// input image be greyscale!
///</Summary>
static Bitmap* ApplySobel(Bitmap* p_Bitmap, const bool& p_Gradient = false);

///<Summary>
/// Simple function to output
/// the given mask, should only
/// pass "c_XMask" or "c_YMask"
/// to this function
///</Summary>
static void OutputMask(const int* const p_Mask);
};

}

#endif

==== SobelHelpers.cpp ====

#include "SobelHelpers.h"

#include <iostream>
#include <algorithm>
#include "GreyscaleHelpers.h"

namespace Xelous
{
///<Summary>
/// Definition of the YMask
///</Summary>
const int SobelHelper::c_YMask[] = 

-1, -2, -1,
0,  0,  0,
+1, +2, +1
};

///<Summary>
/// Definition of the XMask
///</Summary>
const int SobelHelper::c_XMask[] =
{
-1, 0, +1,
-2, 0, +2,
-1, 0, +1
};

///<Summary>
/// Function to carry out the sobel
/// operation, it is recommended the
/// input image be greyscale!
///</Summary>
Bitmap* SobelHelper::ApplySobel(Bitmap* p_Bitmap,
const bool& p_Gradient)
{
// Create a result image with RGB channels
Bitmap* l_result = nullptr;
l_result = new Bitmap(p_Bitmap->width(), p_Bitmap->height(), 1, 3);
if (l_result)
{
double l_Gx;
double l_Gy;

// Single loops through the first image
for (int y = 1; y < (p_Bitmap->height() - 1); ++y)
{
for (int x = 1; x < (p_Bitmap->width() - 1); ++x)
{
// For each pixel, clear these temporary values
l_Gx = 0;
l_Gy = 0;

// Loop through the pixel offset by it's
// neighbours and sum them with the mask
// into the temporary values, this is
// the 3 x 3 window over and around the
// target pixel
for (int row = 0; row < 3; ++row)
{
for (int col = 0; col < 3; ++col)
{
// The X-Y coordinate of the pixel
// masking around the target from
// the main loop
int l_PixelX = x + (row - 1);
int l_PixelY = y + (col - 1);

// The value from the red channel
// from the original image
int l_pixelValue = static_cast<int>(*p_Bitmap->data(l_PixelX, l_PixelY, 0, ColourChannels::Red));
// We could have picked any channel
// from our grey scale image, as they
// should be the same

// Calculate the index in the mask
// from the row & column we've within
// out 3 x 3 grids
int l_index = (row * 3) + col;
l_Gx += (c_XMask[l_index] * l_pixelValue);
l_Gy += (c_YMask[l_index] * l_pixelValue);
}
}

// Summing is the default operation
double l_sum = std::abs(l_Gx) + std::abs(l_Gy);
// If we apply the gradient function
if (p_Gradient)
{
l_sum = std::sqrt((l_Gx * l_Gx) + (l_Gy * l_Gy));
}

// Convert the resulting sum into an integer &
// assign this to the three channels in the result
// image
int l_value = GreyscaleHelper::DoubleToInteger(l_sum);
*l_result->data(x, y, 0, ColourChannels::Red) = l_value;
*l_result->data(x, y, 0, ColourChannels::Green) = l_value;
*l_result->data(x, y, 0, ColourChannels::Blue) = l_value;
}
}
}
return l_result;
}

///<Summary>
/// Simple function to output
/// the given mask, should only
/// pass "c_XMask" or "c_YMask"
/// to this function
///</Summary>
void SobelHelper::OutputMask(const int* const p_Mask)
{
using namespace std;

cout << "{ " << endl;
for (int rows = 0; rows < 3; ++rows)
{
cout << "{";
for (int cols = 0; cols < 3; ++cols)
{
cout << " " << p_Mask[(rows * 3) + cols] << " ";
}
cout << " }" << endl;
}
cout << "}" << endl;
}

}

==== main.cpp ====

Xelous::Bitmap* l_BmpSobel = LoadTest("C:\\Code\\Items1.bmp");
Xelous::GreyscaleHelper::ConvertToGreyscale(l_BmpSobel, Xelous::GreyscaleAlgorithms::Luminosity);
Xelous::Bitmap* l_SobelResult = Xelous::SobelHelper::ApplySobel(l_BmpSobel, true);
if (l_SobelResult)
{
l_SobelResult->save("C:\\Code\\Items1_Sobel.bmp");
delete l_SobelResult;
}
delete l_BmpSobel;

2 comments:

  1. god damn it please change to wordpress its hard to read

    ReplyDelete
    Replies
    1. Sorry, am I holding up your doing your homework?... Maybe if you didn't read it, and just used copy & paste it'd be quicker?... *tut* Kids today, they want the moon on a stick!

      Delete