180 lines
4.5 KiB
C++
180 lines
4.5 KiB
C++
#include "convolution.h"
|
|
|
|
/** Overloaded constructor */
|
|
Convolution::Convolution(PNM* img) :
|
|
Transformation(img)
|
|
{
|
|
}
|
|
|
|
Convolution::Convolution(PNM* img, ImageViewer* iv) :
|
|
Transformation(img, iv)
|
|
{
|
|
}
|
|
|
|
/** Returns a convoluted form of the image */
|
|
PNM* Convolution::transform()
|
|
{
|
|
return convolute(getMask(3, Normalize), RepeatEdge);
|
|
}
|
|
|
|
/** Returns a sizeXsize matrix with the center point equal 1.0 */
|
|
math::matrix<float> Convolution::getMask(int size, Mode mode = Normalize)
|
|
{
|
|
math::matrix<float> mask(size, size);
|
|
|
|
for (int x=0; x<size; x++)
|
|
for (int y=0; y<size; y++)
|
|
{
|
|
mask[x][y] = 0;
|
|
}
|
|
|
|
int half=size/2;
|
|
|
|
mask[half][half]=1;
|
|
|
|
|
|
return mask;
|
|
}
|
|
|
|
/** Does the convolution process for all pixels using the given mask. */
|
|
PNM* Convolution::convolute(math::matrix<float> mask, Mode mode = CyclicEdge)
|
|
{
|
|
int width = image->width(),
|
|
height = image->height();
|
|
int size=mask.rowno();
|
|
|
|
PNM* newImage = new PNM(width, height, image->format());
|
|
math::matrix<float> red_window(size, size);
|
|
math::matrix<float> blue_window(size, size);
|
|
math::matrix<float> gray_window(size, size);
|
|
math::matrix<float> green_window(size, size);
|
|
|
|
float mask_weight=sum(mask);
|
|
float red_sum;
|
|
float green_sum;
|
|
float blue_sum;
|
|
float gray_sum;
|
|
|
|
|
|
|
|
for (int x=0; x<width; x++)
|
|
for (int y=0; y<height; y++)
|
|
{
|
|
|
|
red_window=getWindow(x,y,size,RChannel,mode);
|
|
blue_window=getWindow(x,y,size,BChannel,mode);
|
|
green_window=getWindow(x,y,size,GChannel,mode);
|
|
//gray_window=getWindow(x,y,size,LChannel,mode);
|
|
|
|
|
|
red_window=join(red_window,mask);
|
|
blue_window=join(blue_window,mask);
|
|
green_window=join(green_window,mask);
|
|
|
|
//gray_window=join(gray_window,mask);
|
|
|
|
red_sum=sum(red_window);
|
|
green_sum=sum(green_window);
|
|
blue_sum=sum(blue_window);
|
|
//gray_sum=sum(gray_window);
|
|
|
|
|
|
if(mask_weight>0)
|
|
{
|
|
red_sum=red_sum/mask_weight;
|
|
blue_sum=blue_sum/mask_weight;
|
|
green_sum=green_sum/mask_weight;
|
|
//gray_sum=gray_sum/mask_weight;
|
|
}
|
|
|
|
|
|
|
|
|
|
if(red_sum>=0 && red_sum<=255 && green_sum>=0 && green_sum<=255 && blue_sum>=0 && blue_sum<=255)
|
|
{
|
|
newImage->setPixel(x,y, QColor(red_sum,green_sum,blue_sum).rgb());
|
|
}
|
|
else if (red_sum>=0 && red_sum<=255 && green_sum>=0 && green_sum<=255)
|
|
{
|
|
int old_blue = qBlue(newImage->pixel(x,y));
|
|
newImage->setPixel(x,y, QColor(red_sum,green_sum,old_blue).rgb());
|
|
}
|
|
else if (blue_sum>=0 && blue_sum<=255 && green_sum>=0 && green_sum<=255)
|
|
{
|
|
int old_red = qRed(newImage->pixel(x,y));
|
|
newImage->setPixel(x,y, QColor(old_red,green_sum,blue_sum).rgb());
|
|
}
|
|
else if (blue_sum>=0 && blue_sum<=255 && red_sum>=0 && red_sum<=255)
|
|
{
|
|
int old_green = qGreen(newImage->pixel(x,y));
|
|
newImage->setPixel(x,y, QColor(red_sum,old_green,blue_sum).rgb());
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
return newImage;
|
|
}
|
|
|
|
/** Joins to matrices by multiplying the A[i,j] with B[i,j].
|
|
* Warning! Both Matrices must be squares with the same size!
|
|
*/
|
|
const math::matrix<float> Convolution::join(math::matrix<float> A, math::matrix<float> B)
|
|
{
|
|
int size = A.rowno();
|
|
math::matrix<float> C(size, size);
|
|
|
|
for (int x=0; x<size; x++)
|
|
for (int y=0; y<size; y++)
|
|
{
|
|
C[x][y]=A[x][y]*B[x][y];
|
|
}
|
|
|
|
|
|
return C;
|
|
}
|
|
|
|
/** Sums all of the matrixes elements */
|
|
const float Convolution::sum(const math::matrix<float> A)
|
|
{
|
|
float sum = 0.0;
|
|
|
|
int size=A.rowno();
|
|
|
|
for (int x=0; x<size; x++)
|
|
for (int y=0; y<size; y++)
|
|
{
|
|
sum=sum+A[x][y];
|
|
}
|
|
|
|
|
|
|
|
return sum;
|
|
|
|
}
|
|
|
|
|
|
/** Returns reflected version of a matrix */
|
|
const math::matrix<float> Convolution::reflection(const math::matrix<float> A)
|
|
{
|
|
int size = A.rowno();
|
|
math::matrix<float> C(size, size);
|
|
int counter_i=0;
|
|
int counter_j=0;
|
|
|
|
|
|
for (int x=size-1; x>=0; x--)
|
|
{
|
|
for (int y=size-1; y>=0; y--)
|
|
{
|
|
C[x][y]=A[counter_i][counter_j];
|
|
counter_j++;
|
|
}
|
|
counter_i++;
|
|
}
|
|
|
|
|
|
return C;
|
|
} |