Clear project - update.
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 02
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania lab02 znajdują się w katalogu ,,02/do_sprawdzenia''
|
|
@ -1,54 +0,0 @@
|
|||||||
#include "conversion_grayscale.h"
|
|
||||||
#include <QDebug>
|
|
||||||
#include <iostream>
|
|
||||||
ConversionGrayscale::ConversionGrayscale(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ConversionGrayscale::ConversionGrayscale(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* ConversionGrayscale::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Grayscale8);
|
|
||||||
|
|
||||||
if (image->format() == QImage::Format_Mono)
|
|
||||||
{
|
|
||||||
for (int x=0; x<width; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y<height; y++)
|
|
||||||
{
|
|
||||||
QColor color = QColor::fromRgb(image->pixel(x,y)); // Getting the pixel(x,y) value
|
|
||||||
newImage->setPixel(x,y, color == Qt::white ? PIXEL_VAL_MAX : PIXEL_VAL_MIN);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
else // if (image->format() == QImage::Format_RGB32)
|
|
||||||
{
|
|
||||||
for (int x=0; x<width; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y<height; y++)
|
|
||||||
{
|
|
||||||
QRgb pixel = image->pixel(x,y); // Getting the pixel(x,y) value
|
|
||||||
//int r = qRed(pixel); // Get the 0-255 value of the R channel
|
|
||||||
//int g = qGreen(pixel); // Get the 0-255 value of the G channel
|
|
||||||
//int b = qBlue(pixel);
|
|
||||||
double r = qRed(pixel)*0.3;
|
|
||||||
double g = qGreen(pixel)*0.6;
|
|
||||||
double b = qBlue(pixel)*0.1;
|
|
||||||
QColor newPixel = QColor(r+g+b,r+g+b,r+g+b);
|
|
||||||
newImage->setPixel(x,y, newPixel.rgb());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
#include "correction.h"
|
|
||||||
|
|
||||||
Correction::Correction(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Correction::Correction(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* Correction::transform()
|
|
||||||
{
|
|
||||||
float shift = getParameter("shift").toFloat();
|
|
||||||
float factor = getParameter("factor").toFloat();
|
|
||||||
float gamma = getParameter("gamma").toFloat();
|
|
||||||
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
for(unsigned int i=0; i<sizeof(LUT)/sizeof(LUT[0]); i++) {
|
|
||||||
|
|
||||||
// Adjusted Value
|
|
||||||
float adjustedValue = 0;
|
|
||||||
|
|
||||||
// shift value
|
|
||||||
adjustedValue = i + shift;
|
|
||||||
|
|
||||||
// multiply by factor
|
|
||||||
adjustedValue = adjustedValue * factor;
|
|
||||||
|
|
||||||
// power by gamma
|
|
||||||
adjustedValue = pow(adjustedValue, gamma);
|
|
||||||
|
|
||||||
// if adjusted value is bigger than 255, will be set to 255
|
|
||||||
if (adjustedValue > PIXEL_VAL_MAX) adjustedValue = PIXEL_VAL_MAX;
|
|
||||||
// if adjusted value is smaller than 0, will be set to 0
|
|
||||||
if (adjustedValue < PIXEL_VAL_MIN) adjustedValue = PIXEL_VAL_MIN;
|
|
||||||
|
|
||||||
//Fill LUT table
|
|
||||||
LUT[i] = adjustedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set new pixels
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
QRgb pixel = image->pixel(x,y);
|
|
||||||
int r = qRed(pixel);
|
|
||||||
int g = qGreen(pixel);
|
|
||||||
int b = qBlue(pixel);
|
|
||||||
QColor newPixel = QColor(LUT[r], LUT[g], LUT[b]);
|
|
||||||
newImage->setPixel(x, y, newPixel.rgb());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 260 KiB |
Before Width: | Height: | Size: 549 KiB |
Before Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 143 KiB |
@ -1,5 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 03
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 3-ego znajdują się w katalogu ,,03/do_sprawdzenia/cpp''
|
|
||||||
|
|
@ -1,136 +0,0 @@
|
|||||||
#include "histogram.h"
|
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
|
|
||||||
Histogram::Histogram(QImage* image)
|
|
||||||
{
|
|
||||||
R = new QHash<int, int>;
|
|
||||||
G = new QHash<int, int>;
|
|
||||||
B = new QHash<int, int>;
|
|
||||||
L = new QHash<int, int>;
|
|
||||||
generate(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
Histogram::~Histogram()
|
|
||||||
{
|
|
||||||
delete R;
|
|
||||||
delete G;
|
|
||||||
delete B;
|
|
||||||
delete L;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Histogram::generate(QImage* image)
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
|
|
||||||
QRgb pixel = image->pixel(x,y);
|
|
||||||
|
|
||||||
// Get color values
|
|
||||||
int r = Histogram::R->value(qRed(pixel));
|
|
||||||
int g = Histogram::G->value(qGreen(pixel));
|
|
||||||
int b = Histogram::B->value(qBlue(pixel));
|
|
||||||
int l = Histogram::L->value(qGray(pixel));
|
|
||||||
|
|
||||||
// Insert color values
|
|
||||||
Histogram::R->insert(qRed(pixel), r+1);
|
|
||||||
Histogram::G->insert(qGreen(pixel), g+1);
|
|
||||||
Histogram::B->insert(qBlue(pixel), b+1);
|
|
||||||
Histogram::L->insert(qGray(pixel), l+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the maximal value of the histogram in the given channel */
|
|
||||||
int Histogram::maximumValue(Channel selectedChannel = RGB)
|
|
||||||
{
|
|
||||||
// Create and set max value
|
|
||||||
int max = 0;
|
|
||||||
|
|
||||||
// Iterate over values
|
|
||||||
for(int i = 0; i < R->size(); i++)
|
|
||||||
{
|
|
||||||
if(R->value(i) > max)
|
|
||||||
{
|
|
||||||
max = R->value(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int i = 0; i < G->size(); i++)
|
|
||||||
{
|
|
||||||
if(G->value(i) > max)
|
|
||||||
{
|
|
||||||
max = G->value(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int i = 0; i < B->size(); i++)
|
|
||||||
{
|
|
||||||
if(B->value(i) > max)
|
|
||||||
{
|
|
||||||
max = B->value(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(int i = 0; i < L->size(); i++)
|
|
||||||
{
|
|
||||||
if(L->value(i) > max)
|
|
||||||
{
|
|
||||||
max = L->value(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Returns a pointer to the given channel QHash<int, int> */
|
|
||||||
QHash<int, int>* Histogram::get(Channel channel = LChannel)
|
|
||||||
{
|
|
||||||
if (channel==LChannel) return L;
|
|
||||||
if (channel==RChannel) return R;
|
|
||||||
if (channel==GChannel) return G;
|
|
||||||
if (channel==BChannel) return B;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a 255 by 100 QImage containing a Histogram for the given channel.
|
|
||||||
* The background is transparent (Alpha 0, RGB=255) */
|
|
||||||
QImage Histogram::getImage(Channel channel = LChannel, QBrush pen = Qt::gray)
|
|
||||||
{
|
|
||||||
// Create blank QImage and fill it with transparent background:
|
|
||||||
QImage histImage(255, 100, QImage::Format_ARGB32);
|
|
||||||
histImage.fill(0);
|
|
||||||
QPainter painter(&histImage);
|
|
||||||
painter.setBrush(Qt::transparent);
|
|
||||||
painter.setPen(Qt::transparent);
|
|
||||||
painter.drawRect(0,0,255,100);
|
|
||||||
|
|
||||||
// Calculate the aspect ratio using the maximal value of the color histograms
|
|
||||||
int maximum = (channel == LChannel ? maximumValue(LChannel) : maximumValue(RGB));
|
|
||||||
float ratio = 100.0/float(maximum);
|
|
||||||
|
|
||||||
// Preparing the painter:
|
|
||||||
painter.setBrush(pen);
|
|
||||||
painter.setPen(pen.color());
|
|
||||||
|
|
||||||
int h;
|
|
||||||
// Draw histogram
|
|
||||||
QHash<int, int>* hist = get(channel);
|
|
||||||
QHash<int, int>::const_iterator cit = hist->begin();
|
|
||||||
|
|
||||||
while (cit != hist->end())
|
|
||||||
{
|
|
||||||
h = 100 - floor(ratio*cit.value());
|
|
||||||
painter.drawLine(cit.key(), h, cit.key(), 100);
|
|
||||||
++cit;
|
|
||||||
}
|
|
||||||
|
|
||||||
return histImage;
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
#include "histogram_equalization.h"
|
|
||||||
|
|
||||||
#include "../histogram.h"
|
|
||||||
|
|
||||||
HistogramEqualization::HistogramEqualization(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HistogramEqualization::HistogramEqualization(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* HistogramEqualization::transform()
|
|
||||||
{
|
|
||||||
float width = image->width();
|
|
||||||
float height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
// Create histogram
|
|
||||||
Histogram* histogram = image->getHistogram();
|
|
||||||
|
|
||||||
// Create pointers QHash<int, int>
|
|
||||||
QHash<int, int>* R = histogram->get(Histogram::RChannel);
|
|
||||||
QHash<int, int>* G = histogram->get(Histogram::GChannel);
|
|
||||||
QHash<int, int>* B = histogram->get(Histogram::BChannel);
|
|
||||||
QHash<int, int>* L = histogram->get(Histogram::LChannel);
|
|
||||||
|
|
||||||
// Setup Channel p
|
|
||||||
float Rp[255];
|
|
||||||
float Gp[255];
|
|
||||||
float Bp[255];
|
|
||||||
float Lp[255];
|
|
||||||
|
|
||||||
// Setup Channel D
|
|
||||||
float RD[255];
|
|
||||||
float GD[255];
|
|
||||||
float BD[255];
|
|
||||||
float LD[255];
|
|
||||||
|
|
||||||
// Get size
|
|
||||||
float size = width * height;
|
|
||||||
|
|
||||||
// Create template values
|
|
||||||
float tempSumR=0;
|
|
||||||
float tempSumG=0;
|
|
||||||
float tempSumB=0;
|
|
||||||
float tempSumL=0;
|
|
||||||
|
|
||||||
|
|
||||||
for (int i=0; i<256; i++)
|
|
||||||
{
|
|
||||||
// Set Xp[i] values
|
|
||||||
Rp[i] = (R->value(i))/(size);
|
|
||||||
Gp[i] = (G->value(i))/(size);
|
|
||||||
Bp[i] = (B->value(i))/(size);
|
|
||||||
Lp[i] = (L->value(i))/(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for(int i=0; i<255; i++)
|
|
||||||
{
|
|
||||||
// Red
|
|
||||||
tempSumR=Rp[i]+tempSumR;
|
|
||||||
RD[i]=tempSumR;
|
|
||||||
|
|
||||||
// Green
|
|
||||||
tempSumG=Gp[i]+tempSumG;
|
|
||||||
GD[i]=tempSumG;
|
|
||||||
|
|
||||||
// Blue
|
|
||||||
tempSumB=Bp[i]+tempSumB;
|
|
||||||
BD[i]=tempSumB;
|
|
||||||
|
|
||||||
// L
|
|
||||||
tempSumL=Lp[i]+tempSumL;
|
|
||||||
LD[i]=tempSumL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// For each pixel
|
|
||||||
for (int x=0; x<width; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y<height; y++)
|
|
||||||
{
|
|
||||||
// Get pixel
|
|
||||||
QRgb pixel = image->pixel(x, y);
|
|
||||||
|
|
||||||
// Set new values
|
|
||||||
int r = RD[qRed(pixel)] * 255;
|
|
||||||
int g = GD[qGreen(pixel)] * 255;
|
|
||||||
int b = BD[qBlue(pixel)] * 255;
|
|
||||||
int l = LD[qGray(pixel)] * 255;
|
|
||||||
|
|
||||||
if (image->format() == QImage::Format_RGB32)
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, QColor(r,g,b).rgb());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
#include "histogram_stretching.h"
|
|
||||||
|
|
||||||
#include "../histogram.h"
|
|
||||||
|
|
||||||
HistogramStretching::HistogramStretching(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HistogramStretching::HistogramStretching(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* HistogramStretching::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
// Create min values
|
|
||||||
int minR = 0;
|
|
||||||
int minG = 0;
|
|
||||||
int minB = 0;
|
|
||||||
int minL = 0;
|
|
||||||
|
|
||||||
// Create max values
|
|
||||||
int maxR = 255;
|
|
||||||
int maxG = 255;
|
|
||||||
int maxB = 255;
|
|
||||||
int maxL = 255;
|
|
||||||
|
|
||||||
// Create histogram
|
|
||||||
Histogram* histogram = image->getHistogram();
|
|
||||||
|
|
||||||
// Create pointers QHash<int, int>
|
|
||||||
QHash<int, int>* R = histogram->get(histogram->RChannel);
|
|
||||||
QHash<int, int>* G = histogram->get(histogram->GChannel);
|
|
||||||
QHash<int, int>* B = histogram->get(histogram->BChannel);
|
|
||||||
QHash<int, int>* L = histogram->get(histogram->LChannel);
|
|
||||||
|
|
||||||
// Increment max values
|
|
||||||
for (int i=0; i<256; i++)
|
|
||||||
{
|
|
||||||
if (R->value(minR) == 0) minR++;
|
|
||||||
if (G->value(minG) == 0) minG++;
|
|
||||||
if (B->value(minB) == 0) minB++;
|
|
||||||
if (L->value(minL) == 0) minL++;
|
|
||||||
}
|
|
||||||
// Decrement max values
|
|
||||||
for (int i=256; i>0; i--)
|
|
||||||
{
|
|
||||||
if (R->value(maxR) == 0) maxR--;
|
|
||||||
if (G->value(maxG) == 0) maxG--;
|
|
||||||
if (B->value(maxB) == 0) maxB--;
|
|
||||||
if (L->value(maxL) == 0) maxL--;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over pixels
|
|
||||||
for (int x=0; x<width; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y<height; y++)
|
|
||||||
{
|
|
||||||
QRgb pixel = image->pixel(x, y);
|
|
||||||
|
|
||||||
// Calculate new values
|
|
||||||
int r = (255/(maxR-minR))*(qRed(pixel)-minR);
|
|
||||||
int g = (255/(maxG-minG))*(qGreen(pixel)-minG);
|
|
||||||
int b = (255/(maxB-minB))*(qBlue(pixel)-minB);
|
|
||||||
int l = (255/(maxL-minL))*(qGray(pixel)-minL);
|
|
||||||
|
|
||||||
if (image->format() == QImage::Format_RGB32)
|
|
||||||
{
|
|
||||||
// Set pixel in RGB32 model
|
|
||||||
newImage->setPixel(x, y, QColor(r,g,b).rgb());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set pixel
|
|
||||||
newImage->setPixel(x, y, l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 04
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 4-ego znajdują się w katalogu ,,04/do_sprawdzenia/cpp/''
|
|
@ -1,46 +0,0 @@
|
|||||||
#include "blur_gaussian.h"
|
|
||||||
|
|
||||||
BlurGaussian::BlurGaussian(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BlurGaussian::BlurGaussian(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* BlurGaussian::transform()
|
|
||||||
{
|
|
||||||
emit message("Blurring...");
|
|
||||||
|
|
||||||
int size = getParameter("size").toInt();
|
|
||||||
radius = (size/2)+1;
|
|
||||||
sigma = getParameter("sigma").toDouble();
|
|
||||||
|
|
||||||
return convolute(getMask(size, Normalize), RepeatEdge);
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float> BlurGaussian::getMask(int size, Mode)
|
|
||||||
{
|
|
||||||
math::matrix<float> mask(size, size);
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
mask(i,j) = getGauss(i-radius, j-radius, sigma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
float BlurGaussian::getGauss(int x, int y, float sigma)
|
|
||||||
{
|
|
||||||
// Calculate a two-dimensional Gaussian function:
|
|
||||||
return (1 / (2 * M_PI * pow(sigma, 2))) * exp(-(pow(x, 2) + pow(y, 2)) / (2 * pow(sigma, 2)));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
#include "blur_linear.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
BlurLinear::BlurLinear(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BlurLinear::BlurLinear(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* BlurLinear::transform()
|
|
||||||
{
|
|
||||||
int maskSize = getParameter("size").toInt();
|
|
||||||
QList<QVariant> tmpMask = getParameter("mask").toList();
|
|
||||||
bool normalize = getParameter("normalize").toBool();
|
|
||||||
|
|
||||||
math::matrix<float> mask(maskSize, maskSize);
|
|
||||||
|
|
||||||
int temp = 0;
|
|
||||||
|
|
||||||
for (int x = 0; x < maskSize; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < maskSize; y++)
|
|
||||||
{
|
|
||||||
std::cout << "value " << tmpMask.at(temp).toDouble() << std::endl;
|
|
||||||
mask(x, y) = tmpMask.at(temp).toDouble();
|
|
||||||
temp++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float sum_mask = sum(mask);
|
|
||||||
|
|
||||||
if (normalize)
|
|
||||||
{
|
|
||||||
if (sum_mask == 0){
|
|
||||||
sum_mask = 1.0;
|
|
||||||
}
|
|
||||||
for (int x = 0; x < maskSize; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < maskSize; y++)
|
|
||||||
{
|
|
||||||
mask(x, y) = mask(x, y) / sum_mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return convolute(mask, RepeatEdge);
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
#include "blur_uniform.h"
|
|
||||||
|
|
||||||
BlurUniform::BlurUniform(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BlurUniform::BlurUniform(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float> BlurUniform::getMask(int size, Mode)
|
|
||||||
{
|
|
||||||
math::matrix<float> mask(size, size);
|
|
||||||
|
|
||||||
for (int i=0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j < size; j++)
|
|
||||||
{
|
|
||||||
mask[i][j] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mask;
|
|
||||||
}
|
|
@ -1,177 +0,0 @@
|
|||||||
#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);
|
|
||||||
|
|
||||||
// Get center of image
|
|
||||||
int center = size/2;
|
|
||||||
|
|
||||||
// Get mask
|
|
||||||
for (int i=0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j < size; j++)
|
|
||||||
{
|
|
||||||
if (i==j && i == center && j == center)
|
|
||||||
{
|
|
||||||
mask[i][j] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mask[i][j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Does the convolution process for all pixels using the given mask. */
|
|
||||||
PNM* Convolution::convolute(math::matrix<float> mask, Mode mode = RepeatEdge)
|
|
||||||
{
|
|
||||||
int width = image->width(),
|
|
||||||
height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
float weight = Convolution::sum(mask);
|
|
||||||
if (weight == 0)
|
|
||||||
{
|
|
||||||
weight = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float> reflection = Convolution::reflection(mask);
|
|
||||||
for (int x=0; x < width ; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y < height; y++)
|
|
||||||
{
|
|
||||||
math::matrix<float> rAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::RChannel, mode), reflection);
|
|
||||||
math::matrix<float> gAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::GChannel, mode), reflection);
|
|
||||||
math::matrix<float> bAcc = Convolution::join(getWindow(x, y, mask.rowno(), Transformation::BChannel, mode), reflection);
|
|
||||||
|
|
||||||
float rAccSum = Convolution::sum(rAcc);
|
|
||||||
float gAccSum = Convolution::sum(gAcc);
|
|
||||||
float bAccSum = Convolution::sum(bAcc);
|
|
||||||
|
|
||||||
|
|
||||||
if (weight != 0)
|
|
||||||
{
|
|
||||||
rAccSum = rAccSum / weight;
|
|
||||||
gAccSum = gAccSum / weight;
|
|
||||||
bAccSum = bAccSum / weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate Red Accumulate Sum
|
|
||||||
if (rAccSum < 0)
|
|
||||||
{
|
|
||||||
rAccSum = 0;
|
|
||||||
}
|
|
||||||
else if (rAccSum > 255)
|
|
||||||
{
|
|
||||||
rAccSum = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate Green Accumulate Sum
|
|
||||||
if (gAccSum < 0)
|
|
||||||
{
|
|
||||||
gAccSum = 0;
|
|
||||||
}
|
|
||||||
else if (gAccSum > 255)
|
|
||||||
{
|
|
||||||
gAccSum = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate Blue Accumulate Sum
|
|
||||||
if (bAccSum < 0)
|
|
||||||
{
|
|
||||||
bAccSum = 0;
|
|
||||||
}
|
|
||||||
else if(bAccSum > 255)
|
|
||||||
{
|
|
||||||
bAccSum = 255;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create pixel
|
|
||||||
QColor newPixel = QColor(rAccSum, gAccSum, bAccSum);
|
|
||||||
|
|
||||||
// Set pixel
|
|
||||||
newImage->setPixel(x,y, newPixel.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 i=0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j < size; j++)
|
|
||||||
{
|
|
||||||
// Multiplication
|
|
||||||
C[i][j] = A[i][j] * B[i][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 i=0; i<size; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j<size; j++)
|
|
||||||
{
|
|
||||||
// Summation
|
|
||||||
sum = sum + A[i][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
|
|
||||||
|
|
||||||
for (int i=0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j=0; j < size; j++)
|
|
||||||
{
|
|
||||||
C[i][j] = A[size-i-1][size-j-1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return C;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 383 KiB |
Before Width: | Height: | Size: 638 KiB |
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 05
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 5-ego znajdują się w katalogu ,,05/do_sprawdzenia/cpp/''
|
|
@ -1,72 +0,0 @@
|
|||||||
#include "bin_gradient.h"
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
BinarizationGradient::BinarizationGradient(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarizationGradient::BinarizationGradient(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* BinarizationGradient::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
|
|
||||||
// Create variables
|
|
||||||
// The pixel value at point (i,j)
|
|
||||||
float I=0;
|
|
||||||
|
|
||||||
// The first component of the gradient at point (i,j)
|
|
||||||
float Gx=0;
|
|
||||||
|
|
||||||
// The second component of the gradient at point (i,j)
|
|
||||||
float Gy=0;
|
|
||||||
|
|
||||||
|
|
||||||
for (int x=0; x < width; x++)
|
|
||||||
{
|
|
||||||
for(int y=0; y < height; y++)
|
|
||||||
{
|
|
||||||
// Get current pixel value
|
|
||||||
QRgb pixel = image->pixel(x, y);
|
|
||||||
I = qGray(pixel);
|
|
||||||
|
|
||||||
// Calculate Gx
|
|
||||||
Gx = Gx + (I * qGray(image->pixel(x+1, y)) - I * qGray(image->pixel(x-1, y)));
|
|
||||||
|
|
||||||
//Calculate Gy
|
|
||||||
Gy = Gy + (I * qGray(image->pixel(x, y+1)) - I * qGray(image->pixel(x, y-1)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate T
|
|
||||||
float T = (max(Gx, Gy) * I) / max(Gx, Gy);
|
|
||||||
|
|
||||||
// Iterate over pixels
|
|
||||||
for (int x=0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y < height; y++)
|
|
||||||
{
|
|
||||||
// Get current pixel
|
|
||||||
QRgb pixel = image->pixel(x, y);
|
|
||||||
if(qGray(pixel) > T)
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, Qt::color1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, Qt::color0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
|||||||
#include "bin_iterbimodal.h"
|
|
||||||
#include "bin_manual.h"
|
|
||||||
#include "conversion_grayscale.h"
|
|
||||||
#include "histogram_equalization.h"
|
|
||||||
#include "../histogram.h"
|
|
||||||
|
|
||||||
|
|
||||||
BinarizationIterBimodal::BinarizationIterBimodal(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarizationIterBimodal::BinarizationIterBimodal(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* BinarizationIterBimodal::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
|
|
||||||
// Create variables
|
|
||||||
HistogramEqualization* equalized_histogram = new HistogramEqualization(image);
|
|
||||||
BinarizationManual* binarization_manual;
|
|
||||||
|
|
||||||
int iter = 1;
|
|
||||||
|
|
||||||
// Threshold
|
|
||||||
int T = 128;
|
|
||||||
|
|
||||||
// New threshold
|
|
||||||
int T_new;
|
|
||||||
|
|
||||||
image = equalized_histogram->transform();
|
|
||||||
|
|
||||||
// Histogram table
|
|
||||||
hg = image->getHistogram()->get(Histogram::LChannel);
|
|
||||||
|
|
||||||
// Calculate new threshold
|
|
||||||
T_new = (avg_saturation(0, T-1) + avg_saturation(T, 255)) / 2;
|
|
||||||
|
|
||||||
while (T_new != T)
|
|
||||||
{
|
|
||||||
T = T_new;
|
|
||||||
|
|
||||||
T_new = (avg_saturation(0, T-1) + avg_saturation(T, 255)) / 2;
|
|
||||||
iter ++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use manual binarization to binaryze image
|
|
||||||
binarization_manual = new BinarizationManual(image);
|
|
||||||
binarization_manual->setParameter("threshold", T);
|
|
||||||
|
|
||||||
// Return binary image
|
|
||||||
newImage = binarization_manual->transform();
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int BinarizationIterBimodal::avg_saturation(int start, int end)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int value;
|
|
||||||
int sum;
|
|
||||||
int counter;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
sum = 1;
|
|
||||||
counter = 1;
|
|
||||||
for (i = start; i <= end; i++)
|
|
||||||
{
|
|
||||||
// Get value
|
|
||||||
value = hg->value(i);
|
|
||||||
sum += value;
|
|
||||||
counter += value * i;
|
|
||||||
}
|
|
||||||
result = counter / sum;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
|||||||
#ifndef BIN_ITERBIMODAL_H
|
|
||||||
#define BIN_ITERBIMODAL_H
|
|
||||||
|
|
||||||
#include "transformation.h"
|
|
||||||
|
|
||||||
|
|
||||||
class BinarizationIterBimodal : public Transformation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BinarizationIterBimodal(PNM*);
|
|
||||||
BinarizationIterBimodal(PNM*, ImageViewer*);
|
|
||||||
|
|
||||||
virtual PNM* transform();
|
|
||||||
|
|
||||||
QHash<int, int> * hg;
|
|
||||||
|
|
||||||
int avg_saturation(int, int);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // BIN_ITERBIMODAL_H
|
|
@ -1,45 +0,0 @@
|
|||||||
#include "bin_manual.h"
|
|
||||||
|
|
||||||
BinarizationManual::BinarizationManual(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarizationManual::BinarizationManual(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* BinarizationManual::transform()
|
|
||||||
{
|
|
||||||
int threshold = getParameter("threshold").toInt();
|
|
||||||
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
|
|
||||||
// Iterate over pixels
|
|
||||||
for (int x=0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y < height; y++)
|
|
||||||
{
|
|
||||||
// Get current pixel
|
|
||||||
QRgb pixel = image->pixel(x, y);
|
|
||||||
if(qGray(pixel) > threshold)
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, Qt::color1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, Qt::color0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,69 +0,0 @@
|
|||||||
#include "bin_niblack.h"
|
|
||||||
#include "transformation.h"
|
|
||||||
|
|
||||||
BinarizationNiblack::BinarizationNiblack(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarizationNiblack::BinarizationNiblack(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* BinarizationNiblack::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
int r = getParameter("r").toInt();
|
|
||||||
double a = getParameter("a").toDouble();
|
|
||||||
|
|
||||||
double arithmetic_mean = 0;
|
|
||||||
double variance = 0;
|
|
||||||
double standard_deviation = 0;
|
|
||||||
math::matrix<float> window;
|
|
||||||
int T;
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
|
|
||||||
for (int x=0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y < height; y++)
|
|
||||||
{
|
|
||||||
// Get current pixel
|
|
||||||
QRgb pixel = image->pixel(x, y);
|
|
||||||
|
|
||||||
//Get current window
|
|
||||||
window = getWindow(x, y, r, LChannel, RepeatEdge);
|
|
||||||
|
|
||||||
// Calculate arithmetic mean
|
|
||||||
arithmetic_mean = window.sum() / pow(r, 2);
|
|
||||||
|
|
||||||
|
|
||||||
// Calculate standard_deviation
|
|
||||||
for (int i = 0; i < r+1; i++){
|
|
||||||
for (int j = 0; i < r+1; i++){
|
|
||||||
variance += pow(window[i][j] - arithmetic_mean, 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
variance /= pow(r, 2);
|
|
||||||
standard_deviation = sqrt(variance);
|
|
||||||
|
|
||||||
// Calculate threshold T
|
|
||||||
T = arithmetic_mean + a * standard_deviation;
|
|
||||||
|
|
||||||
if(qGray(pixel) > T)
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, Qt::color1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, Qt::color0);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
|||||||
#include "bin_otsu.h"
|
|
||||||
|
|
||||||
#include "histogram_equalization.h"
|
|
||||||
#include "../histogram.h"
|
|
||||||
|
|
||||||
BinarizationOtsu::BinarizationOtsu(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarizationOtsu::BinarizationOtsu(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* BinarizationOtsu::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
HistogramEqualization* equalized_histogram = new HistogramEqualization(image);
|
|
||||||
QHash<int, int> * hg;
|
|
||||||
|
|
||||||
// Number od pixels in image
|
|
||||||
int N = width * height;
|
|
||||||
|
|
||||||
image = equalized_histogram->transform();
|
|
||||||
|
|
||||||
// Histogram table
|
|
||||||
hg = image->getHistogram()->get(Histogram::LChannel);
|
|
||||||
|
|
||||||
|
|
||||||
int value;
|
|
||||||
double bcv[256];
|
|
||||||
|
|
||||||
int sum_1 = 0;
|
|
||||||
int sum2 = 0;
|
|
||||||
|
|
||||||
double u_b;
|
|
||||||
double u_f;
|
|
||||||
double W_b;
|
|
||||||
double W_f;
|
|
||||||
|
|
||||||
for (int t=0; t < 255; t++)
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int j=0; j < t; j++)
|
|
||||||
{
|
|
||||||
value = image->getHistogram()->get(Histogram::LChannel)->value(j);
|
|
||||||
sum_1 += value;
|
|
||||||
}
|
|
||||||
|
|
||||||
W_b = sum_1 / pow(255, 2);
|
|
||||||
|
|
||||||
for (int j=0; j < t; j++)
|
|
||||||
{
|
|
||||||
value = image->getHistogram()->get(Histogram::LChannel)->value(j);
|
|
||||||
sum2 += value * j;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum_1 == 0)
|
|
||||||
{
|
|
||||||
u_b = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u_b = sum2 / sum_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sum_1 = 0;
|
|
||||||
sum2 = 0;
|
|
||||||
|
|
||||||
for (int j=t; j < 255; j++)
|
|
||||||
{
|
|
||||||
value = image->getHistogram()->get(Histogram::LChannel)->value(j);
|
|
||||||
sum_1 += value;
|
|
||||||
}
|
|
||||||
|
|
||||||
W_f = sum_1 / pow(255, 2);
|
|
||||||
|
|
||||||
for (int j=t; j < 255; j++)
|
|
||||||
{
|
|
||||||
value = image->getHistogram()->get(Histogram::LChannel)->value(j);
|
|
||||||
sum2 += value * j;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sum_1 == 0)
|
|
||||||
{
|
|
||||||
u_f = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
u_f = sum2 / sum_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bcv[t]= W_b * W_f * pow(u_b - u_f, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
int T = 0;
|
|
||||||
for (int j=0; j< 255;j++)
|
|
||||||
{
|
|
||||||
if (bcv[j] > bcv[T])
|
|
||||||
{
|
|
||||||
T=j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over pixels
|
|
||||||
for (int x=0; x<width; x++)
|
|
||||||
{
|
|
||||||
for (int y=0; y < height; y++)
|
|
||||||
{
|
|
||||||
// Get current pixel
|
|
||||||
QRgb pixel = image->pixel(x, y);
|
|
||||||
int l = qGray(pixel);
|
|
||||||
|
|
||||||
newImage->setPixel(x,y, l < T ? Qt::color0 : Qt::color1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 18 KiB |
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 06
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 6-ego znajdują się w katalogu ,,06/do_sprawdzenia/cpp/''
|
|
Before Width: | Height: | Size: 604 KiB |
Before Width: | Height: | Size: 20 KiB |
@ -1,98 +0,0 @@
|
|||||||
#include "noise_bilateral.h"
|
|
||||||
|
|
||||||
NoiseBilateral::NoiseBilateral(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NoiseBilateral::NoiseBilateral(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* NoiseBilateral::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
sigma_d = getParameter("sigma_d").toInt();
|
|
||||||
sigma_r = getParameter("sigma_r").toInt();
|
|
||||||
|
|
||||||
radius = sigma_d;
|
|
||||||
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
if (image->format() == QImage::Format_Indexed8)
|
|
||||||
{
|
|
||||||
// Get calculated value for LChannel and set as new pixel
|
|
||||||
newImage->setPixel(x, y, calcVal(x, y, LChannel));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get calculated values for RGB channels
|
|
||||||
int r_calc = calcVal(x, y, RChannel);
|
|
||||||
int g_calc = calcVal(x, y, GChannel);
|
|
||||||
int b_calc = calcVal(x, y, BChannel);
|
|
||||||
|
|
||||||
|
|
||||||
QColor color = QColor(r_calc, g_calc, b_calc);
|
|
||||||
newImage->setPixel(x, y, color.rgb());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NoiseBilateral::calcVal(int x, int y, Channel channel)
|
|
||||||
{
|
|
||||||
// Set variables
|
|
||||||
float top = 0;
|
|
||||||
float bottom = 0;
|
|
||||||
|
|
||||||
// Get window
|
|
||||||
math::matrix<float> window = getWindow(x,y, radius, channel, RepeatEdge);
|
|
||||||
|
|
||||||
// Get size of matrix
|
|
||||||
int window_row_number = window.rowno();
|
|
||||||
int window_col_number = window.colno();
|
|
||||||
|
|
||||||
// Get central value
|
|
||||||
float central = window[window_row_number / 2][window_col_number / 2];
|
|
||||||
|
|
||||||
for (int i = 0; i < window_col_number; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < window_row_number; j++)
|
|
||||||
{
|
|
||||||
// Get Point in (i, j)
|
|
||||||
QPoint p1(i,j);
|
|
||||||
|
|
||||||
// Get second Point
|
|
||||||
QPoint p2(window_row_number / 2, window_col_number / 2);
|
|
||||||
|
|
||||||
// Calculate top value
|
|
||||||
top = top + window[i][j] * colorCloseness(window[i][j], central) * spatialCloseness(p1, p2);
|
|
||||||
|
|
||||||
// Calculate bottom value
|
|
||||||
bottom = bottom + colorCloseness(window[i][j], central) * spatialCloseness(p1, p2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return top / bottom;
|
|
||||||
}
|
|
||||||
|
|
||||||
float NoiseBilateral::colorCloseness(int val1, int val2)
|
|
||||||
{
|
|
||||||
float result = exp(-(pow(val1 - val2, 2) / (2 * sigma_r * sigma_r)));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
float NoiseBilateral::spatialCloseness(QPoint point1, QPoint point2)
|
|
||||||
{
|
|
||||||
float result = exp(-(pow(point1.x() - point2.x(), 2) + pow(point1.y() - point2.y(), 2) / (2 * sigma_d * sigma_d)));
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,112 +0,0 @@
|
|||||||
#include "noise_median.h"
|
|
||||||
|
|
||||||
NoiseMedian::NoiseMedian(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
NoiseMedian::NoiseMedian(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* NoiseMedian::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (image->format() == QImage::Format_Indexed8)
|
|
||||||
{
|
|
||||||
// Get median value for LChannel and set as new pixel
|
|
||||||
newImage->setPixel(i, j, getMedian(i, j, LChannel));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get median values for RGB channels
|
|
||||||
int r_med = getMedian(i, j, RChannel);
|
|
||||||
int g_med = getMedian(i, j, GChannel);
|
|
||||||
int b_med = getMedian(i, j, BChannel);
|
|
||||||
|
|
||||||
// Create new color
|
|
||||||
QColor color = QColor(r_med, g_med, b_med);
|
|
||||||
|
|
||||||
// Set new pixel with rgb color
|
|
||||||
newImage->setPixel(i, j, color.rgb());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NoiseMedian::getMedian(int x, int y, Channel channel)
|
|
||||||
{
|
|
||||||
int radius = getParameter("radius").toInt();
|
|
||||||
int window_size = 2 * radius + 1;
|
|
||||||
|
|
||||||
math::matrix<int> window = getWindow(x, y, window_size, channel, RepeatEdge);
|
|
||||||
std::vector<int> result; //list does not provide a subscript operator
|
|
||||||
|
|
||||||
for(std::size_t i=0; i < window.rowno(); i++){
|
|
||||||
for(std::size_t j=0; j < window.colno(); j++){
|
|
||||||
result.push_back(window[i][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::sort(result.begin(), result.end());
|
|
||||||
int middle = result.size()/2;
|
|
||||||
return result[middle];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// Different solution
|
|
||||||
int NoiseMedian::getMedian(int x, int y, Channel channel)
|
|
||||||
{
|
|
||||||
int radius = getParameter("radius").toInt();
|
|
||||||
int window_size = 2 * radius + 1;
|
|
||||||
|
|
||||||
int powSize = size*size;
|
|
||||||
int window[powSize];
|
|
||||||
|
|
||||||
int sr = 0;
|
|
||||||
int sc = 0;
|
|
||||||
int lp = 0;
|
|
||||||
float value;
|
|
||||||
|
|
||||||
for (sr = x-radius; sr <= x+radius; sr++)
|
|
||||||
{
|
|
||||||
for (sc = y-radius; sc <= y+radius; sc++)
|
|
||||||
{
|
|
||||||
QRgb color = getPixel(sr, sc, CyclicEdge);
|
|
||||||
|
|
||||||
switch(channel)
|
|
||||||
{
|
|
||||||
case LChannel:
|
|
||||||
value = qGray (color);
|
|
||||||
break;
|
|
||||||
case RChannel:
|
|
||||||
value = qRed (color);
|
|
||||||
break;
|
|
||||||
case GChannel:
|
|
||||||
value = qGreen(color);
|
|
||||||
break;
|
|
||||||
case BChannel:
|
|
||||||
value = qBlue (color);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
window[lp++] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::sort(window, window + powSize);
|
|
||||||
int center = powSize / 2;
|
|
||||||
int result = window[center];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
*/
|
|
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 07
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 7-ego znajdują się w katalogu ,,07/do_sprawdzenia/cpp/''
|
|
Before Width: | Height: | Size: 341 KiB |
Before Width: | Height: | Size: 348 KiB |
@ -1,28 +0,0 @@
|
|||||||
#include "morph_dilate.h"
|
|
||||||
|
|
||||||
MorphDilate::MorphDilate(PNM* img) :
|
|
||||||
MorphologicalOperator(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MorphDilate::MorphDilate(PNM* img, ImageViewer* iv) :
|
|
||||||
MorphologicalOperator(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const int MorphDilate::morph(math::matrix<float> window, math::matrix<bool> se)
|
|
||||||
{
|
|
||||||
float min = PIXEL_VAL_MAX + 1;
|
|
||||||
|
|
||||||
for (int i = 0; i < int(window.colsize()); i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < int(window.rowsize()); j++)
|
|
||||||
{
|
|
||||||
if (se[i][j] == true && window[i][j] < min)
|
|
||||||
{
|
|
||||||
min = window[i][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return min;
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
#include "morph_erode.h"
|
|
||||||
|
|
||||||
MorphErode::MorphErode(PNM* img) :
|
|
||||||
MorphologicalOperator(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MorphErode::MorphErode(PNM* img, ImageViewer* iv) :
|
|
||||||
MorphologicalOperator(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const int MorphErode::morph(math::matrix<float> window, math::matrix<bool> se)
|
|
||||||
{
|
|
||||||
float max = 0.0;
|
|
||||||
|
|
||||||
for (int i = 0; i < int(window.colsize()); i++)
|
|
||||||
{
|
|
||||||
for(int j = 0; j < int(window.rowsize()); j++)
|
|
||||||
{
|
|
||||||
if(se[i][j] == true && window[i][j] > max)
|
|
||||||
{
|
|
||||||
max = window[i][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return max;
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
#include "morph_openclose.h"
|
|
||||||
|
|
||||||
#include "morph_erode.h"
|
|
||||||
#include "morph_dilate.h"
|
|
||||||
|
|
||||||
MorphOpenClose::MorphOpenClose(PNM* img) :
|
|
||||||
MorphologicalOperator(img), m_type(Open)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MorphOpenClose::MorphOpenClose(PNM* img, ImageViewer* iv) :
|
|
||||||
MorphologicalOperator(img, iv), m_type(Open)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* MorphOpenClose::transform()
|
|
||||||
{
|
|
||||||
int size = getParameter("size").toInt();;
|
|
||||||
SE shape = (SE) getParameter("shape").toInt();
|
|
||||||
m_type = (Type) getParameter("type").toInt();
|
|
||||||
|
|
||||||
if (m_type == Open)
|
|
||||||
{
|
|
||||||
return dilate(erode(image, size, shape), size, shape);
|
|
||||||
}
|
|
||||||
else if (m_type == Close)
|
|
||||||
{
|
|
||||||
return erode(dilate(image, size, shape), size, shape);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return image;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* MorphOpenClose::erode(PNM* image, int size, SE shape)
|
|
||||||
{
|
|
||||||
MorphErode e(image, getSupervisor());
|
|
||||||
e.setParameter("silent", true);
|
|
||||||
e.setParameter("shape", shape);
|
|
||||||
e.setParameter("size", size);
|
|
||||||
|
|
||||||
return e.transform();
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* MorphOpenClose::dilate(PNM* image, int size, SE shape)
|
|
||||||
{
|
|
||||||
MorphDilate e(image, getSupervisor());
|
|
||||||
e.setParameter("silent", true);
|
|
||||||
e.setParameter("shape", shape);
|
|
||||||
e.setParameter("size", size);
|
|
||||||
|
|
||||||
return e.transform();
|
|
||||||
}
|
|
@ -1,219 +0,0 @@
|
|||||||
#include "morphological_operator.h"
|
|
||||||
|
|
||||||
MorphologicalOperator::MorphologicalOperator(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MorphologicalOperator::MorphologicalOperator(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// abstract
|
|
||||||
const int MorphologicalOperator::morph(math::matrix<float>, math::matrix<bool>)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<bool> MorphologicalOperator::getSE(int size, SE shape)
|
|
||||||
{
|
|
||||||
switch (shape)
|
|
||||||
{
|
|
||||||
case Square: return seSquare(size);
|
|
||||||
case Cross: return seCross(size);
|
|
||||||
case XCross: return seXCross(size);
|
|
||||||
case VLine: return seVLine(size);
|
|
||||||
case HLine: return seHLine(size);
|
|
||||||
default: return seSquare(size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
math::matrix<bool> MorphologicalOperator::seSquare(int size)
|
|
||||||
{
|
|
||||||
math::matrix<bool> ret(size, size);
|
|
||||||
|
|
||||||
// set true in each field
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
ret[i][j] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<bool> MorphologicalOperator::seCross(int size)
|
|
||||||
{
|
|
||||||
math::matrix<bool> ret(size, size);
|
|
||||||
|
|
||||||
int half = size / 2;
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
if (i == half || j == half)
|
|
||||||
{
|
|
||||||
ret[i][j] = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret[i][j] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<bool> MorphologicalOperator::seXCross(int size)
|
|
||||||
{
|
|
||||||
math::matrix<bool> ret(size, size);
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
if (i == j)
|
|
||||||
{
|
|
||||||
ret[i][j] = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret[i][j] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<bool> MorphologicalOperator::seVLine(int size)
|
|
||||||
{
|
|
||||||
math::matrix<bool> ret(size, size);
|
|
||||||
|
|
||||||
int half = size / 2;
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
if (j == half)
|
|
||||||
{
|
|
||||||
ret[i][j] = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret[i][j] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<bool> MorphologicalOperator::seHLine(int size)
|
|
||||||
{
|
|
||||||
math::matrix<bool> ret(size, size);
|
|
||||||
|
|
||||||
|
|
||||||
int half = size / 2;
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
if (i == half)
|
|
||||||
{
|
|
||||||
ret[i][j] = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ret[i][j] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* MorphologicalOperator::transform()
|
|
||||||
{
|
|
||||||
int size = getParameter("size").toInt();
|
|
||||||
SE shape = (MorphologicalOperator::SE) getParameter("shape").toInt();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(image->width(), image->height(), QImage::Format_RGB32);
|
|
||||||
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
int half = int(size / 2);
|
|
||||||
|
|
||||||
if (image->format() == QImage::Format_Mono)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
math::matrix<float> L_matrix = getWindow(x, y, size, LChannel, RepeatEdge);
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
L_matrix[i][j] = qGray(getPixel((x - half) + i, (y - half) + j, RepeatEdge));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int l = morph(L_matrix, getSE(size, shape));
|
|
||||||
newImage->setPixel(x, y, l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
|
|
||||||
math::matrix<float> R_matrix = getWindow(x, y, size, RChannel, RepeatEdge);
|
|
||||||
math::matrix<float> G_matrix = getWindow(x, y, size, GChannel, RepeatEdge);
|
|
||||||
math::matrix<float> B_matrix = getWindow(x, y, size, BChannel, RepeatEdge);
|
|
||||||
|
|
||||||
QRgb pixel = image->pixel(x,y);
|
|
||||||
int r = qRed(pixel);
|
|
||||||
int g = qGreen(pixel);
|
|
||||||
int b = qBlue(pixel);
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
R_matrix[i][j] = qRed(getPixel((x - half) + j, (y - half) + i, RepeatEdge));
|
|
||||||
B_matrix[i][j] = qBlue(getPixel((x - half) + j, (y - half) + i, RepeatEdge));
|
|
||||||
G_matrix[i][j] = qGreen(getPixel((x - half) + j, (y - half) + i, RepeatEdge));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
r = morph(R_matrix, getSE(size, shape));
|
|
||||||
g = morph(G_matrix, getSE(size, shape));
|
|
||||||
b = morph(B_matrix, getSE(size, shape));
|
|
||||||
|
|
||||||
QColor newPixel = QColor(r,g,b);
|
|
||||||
newImage->setPixel(x, y, newPixel.rgb());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 08
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 8-ego znajdują się w katalogu ,,08/do_sprawdzenia/cpp/''
|
|
@ -1,105 +0,0 @@
|
|||||||
#include "edge_gradient.h"
|
|
||||||
|
|
||||||
EdgeGradient::EdgeGradient(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeGradient::EdgeGradient(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* EdgeGradient::verticalDetection()
|
|
||||||
{
|
|
||||||
return convolute(g_y, RepeatEdge);
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* EdgeGradient::horizontalDetection()
|
|
||||||
{
|
|
||||||
return convolute(g_x, RepeatEdge);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int EdgeGradient::calcValue(int i, int j, Channel channel, PNM* img_x, PNM* img_y)
|
|
||||||
{
|
|
||||||
int value_x, value_y;
|
|
||||||
double power_x, power_y;
|
|
||||||
int value_xy;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
QRgb pixel_x = img_x->pixel(i, j);
|
|
||||||
QRgb pixel_y = img_y->pixel(i, j);
|
|
||||||
|
|
||||||
switch(channel)
|
|
||||||
{
|
|
||||||
|
|
||||||
case RChannel:
|
|
||||||
value_x = qRed(pixel_x);
|
|
||||||
value_y = qRed(pixel_y);
|
|
||||||
break;
|
|
||||||
case GChannel:
|
|
||||||
value_x = qGreen(pixel_x);
|
|
||||||
value_y = qGreen(pixel_y);
|
|
||||||
break;
|
|
||||||
case BChannel:
|
|
||||||
value_x = qBlue(pixel_x);
|
|
||||||
value_y = qBlue(pixel_y);
|
|
||||||
break;
|
|
||||||
case LChannel:
|
|
||||||
value_x = qGray(pixel_x);
|
|
||||||
value_y = qGray(pixel_y);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
power_x = pow(value_x, 2);
|
|
||||||
power_y = pow(value_y, 2);
|
|
||||||
|
|
||||||
value_xy = (int) sqrt(power_x + power_y);
|
|
||||||
|
|
||||||
result = std::max(0, std::min(255, value_xy));
|
|
||||||
|
|
||||||
return result;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PNM* EdgeGradient::transform()
|
|
||||||
{
|
|
||||||
PNM* newImage = new PNM(image->width(), image->height(), image->format());
|
|
||||||
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
// Gradient image by x
|
|
||||||
PNM* img_x = horizontalDetection();
|
|
||||||
|
|
||||||
// Gradient image by y
|
|
||||||
PNM* img_y = verticalDetection();
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (image->format() == QImage::Format_Indexed8)
|
|
||||||
{
|
|
||||||
// Calculate gray pixel value
|
|
||||||
int l = calcValue(i, j, LChannel, img_x, img_y);
|
|
||||||
newImage->setPixel(i, j, l);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Calculate RGB values for pixel
|
|
||||||
int r = calcValue(i, j, RChannel, img_x, img_y);
|
|
||||||
int g = calcValue(i, j, GChannel, img_x, img_y);
|
|
||||||
int b = calcValue(i, j, BChannel, img_x, img_y);
|
|
||||||
|
|
||||||
QColor color = QColor(r, g, b);
|
|
||||||
newImage->setPixel(i, j, color.rgb());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
|||||||
#ifndef EDGE_GRADIENT_H
|
|
||||||
#define EDGE_GRADIENT_H
|
|
||||||
|
|
||||||
#include "convolution.h"
|
|
||||||
|
|
||||||
class EdgeGradient : public Convolution
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EdgeGradient(PNM*);
|
|
||||||
EdgeGradient(PNM*, ImageViewer*);
|
|
||||||
|
|
||||||
virtual PNM* transform();
|
|
||||||
|
|
||||||
PNM* verticalDetection();
|
|
||||||
PNM* horizontalDetection();
|
|
||||||
int calcValue(int i, int j, Channel channel, PNM* img_x, PNM* img_y);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void prepareMatrices() = 0;
|
|
||||||
math::matrix<float> g_x,
|
|
||||||
g_y;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDGE_GRADIENT_H
|
|
@ -1,33 +0,0 @@
|
|||||||
#include "edge_laplacian.h"
|
|
||||||
|
|
||||||
EdgeLaplacian::EdgeLaplacian(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeLaplacian::EdgeLaplacian(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float> EdgeLaplacian::getMask(int, Mode)
|
|
||||||
{
|
|
||||||
int size = getParameter("size").toInt();
|
|
||||||
math::matrix<float> mask(size, size);
|
|
||||||
|
|
||||||
int center = size / 2;
|
|
||||||
|
|
||||||
for (int i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < size; j++)
|
|
||||||
{
|
|
||||||
mask(i, j) = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate center element of mask
|
|
||||||
mask(center, center) = pow(size, 2) - 1;
|
|
||||||
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
|||||||
#include "edge_laplacian_of_gauss.h"
|
|
||||||
|
|
||||||
#include "blur_gaussian.h"
|
|
||||||
|
|
||||||
EdgeLaplaceOfGauss::EdgeLaplaceOfGauss(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeLaplaceOfGauss::EdgeLaplaceOfGauss(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float> EdgeLaplaceOfGauss::getMask()
|
|
||||||
{
|
|
||||||
size = getParameter("size").toInt();
|
|
||||||
double sigma = getParameter("sigma").toDouble();
|
|
||||||
|
|
||||||
math::matrix<float> mask(size, size);
|
|
||||||
|
|
||||||
int center = -size / 2;
|
|
||||||
|
|
||||||
|
|
||||||
for (int x = 0, k = center; x < size; x++, k++)
|
|
||||||
{
|
|
||||||
for (int y = 0, l = center; y < size; y++, l++)
|
|
||||||
{
|
|
||||||
mask(x, y) = getLoG(k, l, sigma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
float EdgeLaplaceOfGauss::getLoG(int x, int y, float s)
|
|
||||||
{
|
|
||||||
int px = pow(x, 2);
|
|
||||||
int py = pow(y, 2);
|
|
||||||
|
|
||||||
float ps = pow(s, 2);
|
|
||||||
int numerator = px + py - 2;
|
|
||||||
|
|
||||||
int gauss = BlurGaussian::getGauss(x, y, ps);
|
|
||||||
|
|
||||||
int result = (numerator / ps) * gauss;
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int EdgeLaplaceOfGauss::getSize()
|
|
||||||
{
|
|
||||||
return size;
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
#ifndef EDGE_LAPLACE_GAUSS_H
|
|
||||||
#define EDGE_LAPLACE_GAUSS_H
|
|
||||||
|
|
||||||
#include "convolution.h"
|
|
||||||
|
|
||||||
class EdgeLaplaceOfGauss : public Convolution
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EdgeLaplaceOfGauss(PNM*);
|
|
||||||
EdgeLaplaceOfGauss(PNM*, ImageViewer*);
|
|
||||||
|
|
||||||
virtual math::matrix<float> getMask();
|
|
||||||
|
|
||||||
static float getLoG(int, int, float);
|
|
||||||
int getSize();
|
|
||||||
|
|
||||||
private:
|
|
||||||
int size;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDGE_LAPLACE_GAUSS_H
|
|
@ -1,19 +0,0 @@
|
|||||||
#include "edge_prewitt.h"
|
|
||||||
|
|
||||||
EdgePrewitt::EdgePrewitt(PNM*img) :
|
|
||||||
EdgeGradient(img)
|
|
||||||
{
|
|
||||||
prepareMatrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgePrewitt::EdgePrewitt(PNM*img, ImageViewer* iv) :
|
|
||||||
EdgeGradient(img, iv)
|
|
||||||
{
|
|
||||||
prepareMatrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgePrewitt::prepareMatrices()
|
|
||||||
{
|
|
||||||
g_x = math::matrix<float>(3, 3, {-1, 0, 1, -1, 0, 1, -1, 0, 1});
|
|
||||||
g_y = math::matrix<float>(3, 3, {-1, -1, -1, 0, 0, 0, 1, 1, 1});
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
#include "edge_roberts.h"
|
|
||||||
|
|
||||||
EdgeRoberts::EdgeRoberts(PNM* img) :
|
|
||||||
EdgeGradient(img)
|
|
||||||
{
|
|
||||||
prepareMatrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeRoberts::EdgeRoberts(PNM* img, ImageViewer* iv) :
|
|
||||||
EdgeGradient(img, iv)
|
|
||||||
{
|
|
||||||
prepareMatrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeRoberts::prepareMatrices()
|
|
||||||
{
|
|
||||||
g_x = math::matrix<float>(2, 2, {1, 0, 0, -1});
|
|
||||||
g_y = math::matrix<float>(2, 2, {0, 1, -1, 0});
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
#include "edge_sobel.h"
|
|
||||||
|
|
||||||
EdgeSobel::EdgeSobel(PNM* img, ImageViewer* iv) :
|
|
||||||
EdgeGradient(img, iv)
|
|
||||||
{
|
|
||||||
prepareMatrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeSobel::EdgeSobel(PNM* img) :
|
|
||||||
EdgeGradient(img)
|
|
||||||
{
|
|
||||||
prepareMatrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeSobel::prepareMatrices()
|
|
||||||
{
|
|
||||||
g_x = math::matrix<float>(3, 3, {-1, 0, 1, -2, 0, 2, -1, 0, 1});
|
|
||||||
g_y = math::matrix<float>(3, 3, {-1, -2, -1, 0, 0, 0, 1, 2, 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float>* EdgeSobel::rawHorizontalDetection()
|
|
||||||
{
|
|
||||||
math::matrix<float>* x_gradient = new math::matrix<float>(this->image->width(), this->image->height());
|
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Not implemented yet!";
|
|
||||||
|
|
||||||
return x_gradient;
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float>* EdgeSobel::rawVerticalDetection()
|
|
||||||
{
|
|
||||||
math::matrix<float>* y_gradient = new math::matrix<float>(this->image->width(), this->image->height());
|
|
||||||
|
|
||||||
qDebug() << Q_FUNC_INFO << "Not implemented yet!";
|
|
||||||
|
|
||||||
return y_gradient;
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
#include "edge_zero.h"
|
|
||||||
|
|
||||||
#include "edge_laplacian_of_gauss.h"
|
|
||||||
|
|
||||||
EdgeZeroCrossing::EdgeZeroCrossing(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeZeroCrossing::EdgeZeroCrossing(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* EdgeZeroCrossing::transform()
|
|
||||||
{
|
|
||||||
int size = getParameter("size").toInt();
|
|
||||||
double sigma = getParameter("sigma").toDouble();
|
|
||||||
int t = getParameter("threshold").toInt();
|
|
||||||
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
int t_width;
|
|
||||||
int t_height;
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Grayscale8);
|
|
||||||
|
|
||||||
EdgeLaplaceOfGauss *laplace_gauss = new EdgeLaplaceOfGauss(image);
|
|
||||||
|
|
||||||
laplace_gauss->setParameter("size", size);
|
|
||||||
laplace_gauss->setParameter("sigma", sigma);
|
|
||||||
|
|
||||||
PNM* transformed_image = laplace_gauss->transform();
|
|
||||||
|
|
||||||
t_width = transformed_image->width();
|
|
||||||
t_height = transformed_image->height();
|
|
||||||
|
|
||||||
for (int i = 0; i < t_width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < t_height; j++)
|
|
||||||
{
|
|
||||||
math::matrix<float> window = laplace_gauss->getWindow(i, j, size, LChannel, RepeatEdge);
|
|
||||||
|
|
||||||
if (window.min() < (128 - t) && window.max() > (128 + t))
|
|
||||||
{
|
|
||||||
QRgb pixel = transformed_image->pixel(i, j);
|
|
||||||
newImage->setPixel(i, j, QColor(pixel).rgb());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newImage->setPixel(i, j, QColor(0,0,0).rgb());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
Before Width: | Height: | Size: 510 KiB |
Before Width: | Height: | Size: 576 KiB |
Before Width: | Height: | Size: 494 KiB |
Before Width: | Height: | Size: 615 KiB |
Before Width: | Height: | Size: 77 KiB |
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 09
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 9-ego znajdują się w katalogu ,,09/do_sprawdzenia/cpp/''
|
|
@ -1,55 +0,0 @@
|
|||||||
#include "edge_sobel.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
EdgeSobel::EdgeSobel(PNM* img, ImageViewer* iv) :
|
|
||||||
EdgeGradient(img, iv)
|
|
||||||
{
|
|
||||||
prepareMatrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeSobel::EdgeSobel(PNM* img) :
|
|
||||||
EdgeGradient(img)
|
|
||||||
{
|
|
||||||
prepareMatrices();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EdgeSobel::prepareMatrices()
|
|
||||||
{
|
|
||||||
g_x = math::matrix<float>(3, 3, {-1, 0, 1, -2, 0, 2, -1, 0, 1});
|
|
||||||
g_y = math::matrix<float>(3, 3, {-1, -2, -1, 0, 0, 0, 1, 2, 1});
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float>* EdgeSobel::rawHorizontalDetection()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
math::matrix<float>* x_gradient = new math::matrix<float>(width, height);
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
(*x_gradient)(i, j) = sum(join(g_x, getWindow(i, j, 3, LChannel, RepeatEdge)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return x_gradient;
|
|
||||||
}
|
|
||||||
|
|
||||||
math::matrix<float>* EdgeSobel::rawVerticalDetection()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
math::matrix<float>* y_gradient = new math::matrix<float>(width, height);
|
|
||||||
math::matrix<float> window;
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
(*y_gradient)(i, j) = sum(join(g_y, getWindow(i, j, 3, LChannel, RepeatEdge)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return y_gradient;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 593 KiB |
Before Width: | Height: | Size: 37 KiB |
@ -1,24 +0,0 @@
|
|||||||
#include "map_height.h"
|
|
||||||
#include "conversion_grayscale.h"
|
|
||||||
|
|
||||||
MapHeight::MapHeight(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MapHeight::MapHeight(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* MapHeight::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
ConversionGrayscale* grayscale = new ConversionGrayscale(image);
|
|
||||||
|
|
||||||
newImage = grayscale->transform();
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
#include "map_horizon.h"
|
|
||||||
|
|
||||||
#include "map_height.h"
|
|
||||||
|
|
||||||
MapHorizon::MapHorizon(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MapHorizon::MapHorizon(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* MapHorizon::transform()
|
|
||||||
{
|
|
||||||
int width = image->width(),
|
|
||||||
height = image->height();
|
|
||||||
|
|
||||||
double scale = getParameter("scale").toDouble();
|
|
||||||
int sun_alpha = getParameter("alpha").toInt();
|
|
||||||
int dx, dy;
|
|
||||||
|
|
||||||
switch (getParameter("direction").toInt())
|
|
||||||
{
|
|
||||||
case NORTH: dx = 0; dy = -1; break;
|
|
||||||
case SOUTH: dx = 0; dy = 1; break;
|
|
||||||
case EAST: dx = 1; dy = 0; break;
|
|
||||||
case WEST: dx = -1; dy = 0; break;
|
|
||||||
default:
|
|
||||||
qWarning() << "Unknown direction!";
|
|
||||||
dx = 0;
|
|
||||||
dy = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
MapHeight* mapHeight = new MapHeight(image);
|
|
||||||
|
|
||||||
image = mapHeight->transform();
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
double alpha = 0;
|
|
||||||
int current_h = qGray(image->pixel(i, j));
|
|
||||||
|
|
||||||
for (int k = i + dx, l = j + dy; k < width && l < height && k >= 0 && l >= 0; k = k + dx, l = l + dy)
|
|
||||||
{
|
|
||||||
int ray_h = qGray(image->pixel(k, l));
|
|
||||||
|
|
||||||
if (current_h < ray_h)
|
|
||||||
{
|
|
||||||
double dist = sqrt(pow(k - i, 2) + pow(l - j, 2)) * scale;
|
|
||||||
double ray_alpha = atan((ray_h - current_h) / dist);
|
|
||||||
|
|
||||||
if (ray_alpha > alpha)
|
|
||||||
{
|
|
||||||
alpha = ray_alpha;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
double delta = alpha - sun_alpha * M_PI / 180;
|
|
||||||
|
|
||||||
if (delta > 0)
|
|
||||||
{
|
|
||||||
double val = cos(delta) * 255;
|
|
||||||
QColor color = QColor(val, val, val);
|
|
||||||
newImage->setPixel(i, j, color.rgb());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QColor color = QColor(255, 255, 255);
|
|
||||||
newImage->setPixel(i, j, color.rgb());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,61 +0,0 @@
|
|||||||
#include "map_normal.h"
|
|
||||||
|
|
||||||
#include "edge_sobel.h"
|
|
||||||
#include "map_height.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
MapNormal::MapNormal(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MapNormal::MapNormal(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* MapNormal::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
// The power constant of the generated normal map.
|
|
||||||
double strength = getParameter("strength").toDouble();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
MapHeight* mh = new MapHeight(image);
|
|
||||||
PNM* image = mh->transform();
|
|
||||||
|
|
||||||
EdgeSobel* es = new EdgeSobel(image);
|
|
||||||
math::matrix<float>* Gx = es->rawHorizontalDetection();
|
|
||||||
math::matrix<float>* Gy = es->rawVerticalDetection();
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
// For each pixel (i,j), determine the coordinates of the vector d
|
|
||||||
float dx = (*Gx)(i, j) / 255;
|
|
||||||
float dy = (*Gy)(i, j) / 255;
|
|
||||||
float dz = 1.0 / strength;
|
|
||||||
|
|
||||||
// Normalise the vector d
|
|
||||||
double dw = sqrt(pow(dx, 2) + pow(dy, 2) + pow(dz, 2));
|
|
||||||
|
|
||||||
// Scale these values to the interval
|
|
||||||
dx = dx / dw;
|
|
||||||
dy = dy / dw;
|
|
||||||
dz = dz / dw;
|
|
||||||
|
|
||||||
dx = (dx + 1.0) * (255 / strength);
|
|
||||||
dy = (dy + 1.0) * (255 / strength);
|
|
||||||
dz = (dz + 1.0) * (255 / strength);
|
|
||||||
|
|
||||||
QColor newPixel = QColor(dx, dy, dz);
|
|
||||||
newImage->setPixel(i, j, newPixel.rgb());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 10
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 10-ego znajdują się w katalogu ,,10/do_sprawdzenia/cpp/''
|
|
@ -1,289 +0,0 @@
|
|||||||
#include "edge_canny.h"
|
|
||||||
|
|
||||||
#include "blur_gaussian.h"
|
|
||||||
#include "conversion_grayscale.h"
|
|
||||||
#include "edge_sobel.h"
|
|
||||||
|
|
||||||
EdgeCanny::EdgeCanny(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
EdgeCanny::EdgeCanny(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void EdgeCanny::Calculate_XY(int i, int j, enum directions dir, int* x1, int* y1, int* x2, int* y2)
|
|
||||||
{
|
|
||||||
switch (dir)
|
|
||||||
{
|
|
||||||
|
|
||||||
case TOP_MIDDLE_BOTTOM_MIDDLE:
|
|
||||||
{
|
|
||||||
*x1 = i - 1;
|
|
||||||
*y1 = j;
|
|
||||||
*x2 = i + 1;
|
|
||||||
*y2 = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case LEFT_MIDDLE_RIGHT_MIDDLE:
|
|
||||||
{
|
|
||||||
*x1 = i;
|
|
||||||
*y1 = j - 1;
|
|
||||||
*x2 = i;
|
|
||||||
*y2 = j + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TOP_RIGHT_BOTTOM_LEFT:
|
|
||||||
{
|
|
||||||
*x1 = i - 1;
|
|
||||||
*y1 = j - 1;
|
|
||||||
*x2 = i + 1;
|
|
||||||
*y2 = j + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TOP_LEFT_BOTTOM_RIGHT:
|
|
||||||
{
|
|
||||||
*x1 = i - 1;
|
|
||||||
*y1 = j + 1;
|
|
||||||
*x2 = i + 1;
|
|
||||||
*y2 = j - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* EdgeCanny::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
|
|
||||||
int upper_thresh = getParameter("upper_threshold").toInt();
|
|
||||||
int lower_thresh = getParameter("lower_threshold").toInt();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, image->format());
|
|
||||||
|
|
||||||
// Create grayscale
|
|
||||||
ConversionGrayscale* grayscale = new ConversionGrayscale(image);
|
|
||||||
PNM* gray_image = grayscale->transform();
|
|
||||||
|
|
||||||
// Blur grayscale
|
|
||||||
BlurGaussian* blur_gaussian = new BlurGaussian(gray_image);
|
|
||||||
blur_gaussian->setParameter("size", 3);
|
|
||||||
blur_gaussian->setParameter("sigma", 1.6);
|
|
||||||
PNM* blur_image = blur_gaussian->transform();
|
|
||||||
|
|
||||||
// Calculate Gx and Gy used EdgeSobel
|
|
||||||
EdgeSobel *es = new EdgeSobel(blur_image);
|
|
||||||
|
|
||||||
math::matrix<float>Gx = *es->rawHorizontalDetection();
|
|
||||||
math::matrix<float>Gy = *es->rawVerticalDetection();
|
|
||||||
|
|
||||||
// Define directions
|
|
||||||
|
|
||||||
|
|
||||||
// Matrix of pixel power
|
|
||||||
math::matrix<float> pixelPower(width, height);
|
|
||||||
|
|
||||||
// Marix od pixel Angle
|
|
||||||
math::matrix<float> pixelAngle(width, height);
|
|
||||||
|
|
||||||
// Matrix of pixel directions
|
|
||||||
math::matrix<directions> pixelDirection(width, height);
|
|
||||||
|
|
||||||
// Matrix of edges
|
|
||||||
math::matrix<bool> edges(width, height);
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
// Calculate current pixel angle
|
|
||||||
pixelAngle[i][j] = atan2(Gy[i][j], Gx[i][j]) * 180 / M_PI;
|
|
||||||
|
|
||||||
// Calculate current pixel power
|
|
||||||
pixelPower[i][j] = sqrt(pow(Gx[i][j], 2) + pow(Gy[i][j], 2));
|
|
||||||
|
|
||||||
// Set current pixel direction
|
|
||||||
if ((pixelAngle[i][j] > 22.5 && pixelAngle[i][j] <= 67.5) ||
|
|
||||||
(pixelAngle[i][j] > 202.5 && pixelAngle[i][j] <= 247.5))
|
|
||||||
{
|
|
||||||
pixelDirection[i][j] = TOP_LEFT_BOTTOM_RIGHT;
|
|
||||||
}
|
|
||||||
else if ((pixelAngle[i][j] > 67.5 && pixelAngle[i][j] <= 112.5) ||
|
|
||||||
(pixelAngle[i][j] > 247.5 && pixelAngle[i][j] <= 292.5))
|
|
||||||
{
|
|
||||||
pixelDirection[i][j] = TOP_MIDDLE_BOTTOM_MIDDLE;
|
|
||||||
}
|
|
||||||
else if ((pixelAngle[i][j] > 112.5 && pixelAngle[i][j] <= 157.5) ||
|
|
||||||
(pixelAngle[i][j] > 292.5 && pixelAngle[i][j] <= 337.5))
|
|
||||||
{
|
|
||||||
pixelDirection[i][j] = TOP_RIGHT_BOTTOM_LEFT;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pixelDirection[i][j] = LEFT_MIDDLE_RIGHT_MIDDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect edges
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (pixelDirection[i][j] == TOP_MIDDLE_BOTTOM_MIDDLE)
|
|
||||||
{
|
|
||||||
if (pixelPower[i][j] > pixelPower[i-1][j] &&
|
|
||||||
pixelPower[i][j] > pixelPower[i+1][j] &&
|
|
||||||
pixelPower[i][j] > upper_thresh)
|
|
||||||
{
|
|
||||||
edges[i][j] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pixelDirection[i][j] == LEFT_MIDDLE_RIGHT_MIDDLE)
|
|
||||||
{
|
|
||||||
if (pixelPower[i][j] > pixelPower[i][j-1] &&
|
|
||||||
pixelPower[i][j] > pixelPower[i][j+1] &&
|
|
||||||
pixelPower[i][j] > upper_thresh)
|
|
||||||
{
|
|
||||||
edges[i][j]=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pixelDirection[i][j] == TOP_LEFT_BOTTOM_RIGHT)
|
|
||||||
{
|
|
||||||
if (pixelPower[i][j] > pixelPower[i-1][j+1] &&
|
|
||||||
pixelPower[i][j] > pixelPower[i+1][j-1] &&
|
|
||||||
pixelPower[i][j] > upper_thresh)
|
|
||||||
{
|
|
||||||
edges[i][j]=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pixelDirection[i][j] == TOP_RIGHT_BOTTOM_LEFT)
|
|
||||||
{
|
|
||||||
if (pixelPower[i][j] > pixelPower[i+1][j+1] &&
|
|
||||||
pixelPower[i][j] > pixelPower[i-1][j-1] &&
|
|
||||||
pixelPower[i][j] > upper_thresh)
|
|
||||||
{
|
|
||||||
edges[i][j]=true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set variables
|
|
||||||
int x1 = 0;
|
|
||||||
int y1 = 0;
|
|
||||||
|
|
||||||
int x2 = 0;
|
|
||||||
int y2 = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (edges[i][j] == true)
|
|
||||||
{
|
|
||||||
Calculate_XY(i, j, pixelDirection[i][j], &x1, &y1, &x2, &y2);
|
|
||||||
|
|
||||||
if (x1 < width && y1 < height && edges[x1][y1] != true)
|
|
||||||
{
|
|
||||||
if (pixelPower[x1][y1] > lower_thresh && pixelDirection[x1][y1] == pixelDirection[i][j])
|
|
||||||
{
|
|
||||||
int x11 = 0;
|
|
||||||
int y11 = 0;
|
|
||||||
int x12 = 0;
|
|
||||||
int y12 = 0;
|
|
||||||
|
|
||||||
Calculate_XY(x1, y1, pixelDirection[x1][y1], &x11, &y11, &x12, &y12);
|
|
||||||
|
|
||||||
if (x11 < width && y11 < height && x12 < width && y12 < height)
|
|
||||||
{
|
|
||||||
if (pixelPower[x11][y11] < pixelPower[x1][y1] && pixelPower[x12][y12] < pixelPower[x1][y1])
|
|
||||||
{
|
|
||||||
edges[x1][y1] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (x11 < width && y11 < height)
|
|
||||||
{
|
|
||||||
if (pixelPower[x11][y11] < pixelPower[x1][y1])
|
|
||||||
{
|
|
||||||
edges[x1][y1] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (x12 < width && y12 < height)
|
|
||||||
{
|
|
||||||
if (pixelPower[x12][y12] < pixelPower[x1][y1])
|
|
||||||
{
|
|
||||||
edges[x1][y1] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x2 < width && y2 < height && edges[x2][y2] != true)
|
|
||||||
{
|
|
||||||
if (pixelPower[x2][y2] > lower_thresh && pixelDirection[x2][y2] == pixelDirection[i][j])
|
|
||||||
{
|
|
||||||
int x21 = 0;
|
|
||||||
int y21 = 0;
|
|
||||||
int x22 = 0;
|
|
||||||
int y22 = 0;
|
|
||||||
|
|
||||||
Calculate_XY(x2, y2, pixelDirection[x2][y2], &x21, &y21, &x22, &y22);
|
|
||||||
|
|
||||||
if (x21 < width && y21 < height && x22 < width && y22 < height)
|
|
||||||
{
|
|
||||||
if (pixelPower[x21][y21] < pixelPower[x2][y2] && pixelPower[x22][y22] < pixelPower[x2][y2])
|
|
||||||
{
|
|
||||||
edges[x2][y2] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (x21 < width && y21 < height)
|
|
||||||
{
|
|
||||||
if (pixelPower[x21][y21] < pixelPower[x2][y2])
|
|
||||||
{
|
|
||||||
edges[x2][y2] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (x22 < width && y22 < height)
|
|
||||||
{
|
|
||||||
if (pixelPower[x22][y22] < pixelPower[x2][y2])
|
|
||||||
{
|
|
||||||
edges[x2][y2] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare new image
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (edges[i][j] == true)
|
|
||||||
{
|
|
||||||
newImage->setPixel(i, j, 255);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newImage->setPixel(i, j, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
#ifndef EDGECANNY_H
|
|
||||||
#define EDGECANNY_H
|
|
||||||
|
|
||||||
#include "convolution.h"
|
|
||||||
|
|
||||||
class EdgeCanny : public Convolution
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
EdgeCanny(PNM*);
|
|
||||||
EdgeCanny(PNM*, ImageViewer*);
|
|
||||||
|
|
||||||
virtual PNM* transform();
|
|
||||||
enum directions {
|
|
||||||
TOP_LEFT_BOTTOM_RIGHT,
|
|
||||||
TOP_RIGHT_BOTTOM_LEFT,
|
|
||||||
TOP_MIDDLE_BOTTOM_MIDDLE,
|
|
||||||
LEFT_MIDDLE_RIGHT_MIDDLE
|
|
||||||
};
|
|
||||||
|
|
||||||
void Calculate_XY(int i, int j, enum directions dir, int* x1, int* y1, int* x2, int* y2);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // EDGECANNY_H
|
|
Before Width: | Height: | Size: 16 KiB |
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 11
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 11-ego znajdują się w katalogu ,,11/do_sprawdzenia/cpp/''
|
|
@ -1,83 +0,0 @@
|
|||||||
#include "bin_gradient.h"
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
BinarizationGradient::BinarizationGradient(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
BinarizationGradient::BinarizationGradient(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* BinarizationGradient::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
int numerator = 0;
|
|
||||||
int denominator = 0;
|
|
||||||
|
|
||||||
// Gx
|
|
||||||
int Gx = 0;
|
|
||||||
|
|
||||||
// Gy
|
|
||||||
int Gy = 0;
|
|
||||||
|
|
||||||
int G = 0;
|
|
||||||
int T = 0;
|
|
||||||
|
|
||||||
//PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
Mode mode = Transformation::RepeatEdge;
|
|
||||||
int I = qGray(getPixel(x, y, mode));
|
|
||||||
|
|
||||||
// Get Gx and Gy
|
|
||||||
Gx = qGray(getPixel(x + 1, y, mode)) - qGray(getPixel(x - 1, y, mode));
|
|
||||||
Gy = qGray(getPixel(x, y + 1, mode)) - qGray(getPixel(x, y - 1, mode));
|
|
||||||
|
|
||||||
if (Gx > Gy)
|
|
||||||
{
|
|
||||||
G = Gx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
G = Gy;
|
|
||||||
}
|
|
||||||
numerator += I * G;
|
|
||||||
denominator += G;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
T = numerator / denominator;
|
|
||||||
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
Mode mode = Transformation::RepeatEdge;
|
|
||||||
QRgb pixel = getPixel(x, y, mode);
|
|
||||||
|
|
||||||
int val = qGray(pixel);
|
|
||||||
|
|
||||||
if (val < T)
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newImage->setPixel(x, y, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,93 +0,0 @@
|
|||||||
#include "hough.h"
|
|
||||||
#include "iostream"
|
|
||||||
#include "conversion_grayscale.h"
|
|
||||||
#include "edge_laplacian.h"
|
|
||||||
|
|
||||||
Hough::Hough(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Hough::Hough(PNM* img, ImageViewer* super) :
|
|
||||||
Transformation(img, super)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* Hough::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
int theta_density = getParameter("theta_density").toInt();
|
|
||||||
bool skip_edge = getParameter("skip_edge_detection").toBool();
|
|
||||||
|
|
||||||
std::cout << "skip_edge: " << skip_edge << std::endl;
|
|
||||||
int theta_size = 180 * theta_density;
|
|
||||||
double max_ro = sqrt(pow(width, 2) + pow(height, 2));
|
|
||||||
|
|
||||||
ConversionGrayscale* gray_scale = new ConversionGrayscale(image);
|
|
||||||
image = gray_scale->transform();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(theta_size, max_ro * 2 + 1, QImage::Format_Grayscale8);
|
|
||||||
|
|
||||||
int new_image_width = newImage->width();
|
|
||||||
int new_image_height = newImage->height();
|
|
||||||
|
|
||||||
math::matrix<float> hough(new_image_width, new_image_height);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (skip_edge == false)
|
|
||||||
{
|
|
||||||
EdgeLaplacian *el = new EdgeLaplacian(image);
|
|
||||||
el->setParameter("size", 7);
|
|
||||||
image = el->transform();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = 0; x < new_image_width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < new_image_height; y++)
|
|
||||||
{
|
|
||||||
hough[x][y] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
double theta = 0.0;
|
|
||||||
double ro = 0;
|
|
||||||
float max = 0;
|
|
||||||
double max_z = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (qGray(image->pixel(i, j)) > 0)
|
|
||||||
{
|
|
||||||
for (int k = 0; k < theta_size; k++)
|
|
||||||
{
|
|
||||||
theta = (k * M_PI) / (theta_density * 180);
|
|
||||||
ro = i * cos(theta) + j * sin(theta);
|
|
||||||
hough[k][ro + max_ro]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
max = hough.max();
|
|
||||||
|
|
||||||
int z;
|
|
||||||
|
|
||||||
for (int x = 0; x < new_image_width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < new_image_height; y++)
|
|
||||||
{
|
|
||||||
z = hough[x][y] * (max / 255);
|
|
||||||
|
|
||||||
newImage->setPixel(x, y, QColor(z, z, z).rgb());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "max_z: " << max_z << std::endl;
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
#include "hough_lines.h"
|
|
||||||
#include "bin_gradient.h"
|
|
||||||
#include "edge_laplacian.h"
|
|
||||||
|
|
||||||
#include "hough.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <Qt>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
HoughLines::HoughLines(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HoughLines::HoughLines(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PNM* HoughLines::transform()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Cut of value from the image;
|
|
||||||
int threshold = getParameter("threshold").toInt();
|
|
||||||
bool drawWholeLines = getParameter("draw_whole_lines").toBool();
|
|
||||||
int theta_density = 3;
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(image->copy());
|
|
||||||
|
|
||||||
EdgeLaplacian el(image);
|
|
||||||
el.setParameter("size", 3);
|
|
||||||
PNM* image_edge = el.transform();
|
|
||||||
|
|
||||||
PNM* image_bin = BinarizationGradient(image_edge).transform();
|
|
||||||
|
|
||||||
Hough h(image_edge);
|
|
||||||
|
|
||||||
h.setParameter("theta_density", theta_density);
|
|
||||||
h.setParameter("skip_edge_detection", true);
|
|
||||||
PNM* image_hough = h.transform();
|
|
||||||
|
|
||||||
int hough_width = image_hough->width();
|
|
||||||
int hough_height = image_hough->height();
|
|
||||||
|
|
||||||
int width = image_bin->width();
|
|
||||||
int height = image_bin->height();
|
|
||||||
|
|
||||||
QPainter qPainter (newImage);
|
|
||||||
qPainter.setPen(Qt::red);
|
|
||||||
|
|
||||||
for (int theta = 0; theta < hough_width; theta++)
|
|
||||||
{
|
|
||||||
for (int rho = 0; rho < hough_height; rho++)
|
|
||||||
{
|
|
||||||
int val = (int) qGray(image_hough->pixel(theta, rho));
|
|
||||||
if (val > threshold)
|
|
||||||
{
|
|
||||||
double rtheta = ((double)theta / 3.0) * M_PI / 180.0;
|
|
||||||
int rrho = rho - hough_height / 2;
|
|
||||||
qPainter.drawLine(0, round(rrho / sin(rtheta)), width - 1, round((rrho - (width - 1) * cos(rtheta)) / sin(rtheta)));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int counter_pixels = 0;
|
|
||||||
if (!drawWholeLines)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
QRgb pixel = image_bin->pixel(x, y);
|
|
||||||
|
|
||||||
if (qGray(pixel) == 0)
|
|
||||||
{
|
|
||||||
counter_pixels++;
|
|
||||||
newImage->setPixel(x, y, image->pixel(x, y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "counter " << counter_pixels << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
Before Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 9.8 KiB |
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 12
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 12-ego znajdują się w katalogu ,,12/do_sprawdzenia/cpp/''
|
|
@ -1,158 +0,0 @@
|
|||||||
#include "corner_harris.h"
|
|
||||||
|
|
||||||
#include "blur_gaussian.h"
|
|
||||||
#include "conversion_grayscale.h"
|
|
||||||
#include "edge_sobel.h"
|
|
||||||
|
|
||||||
CornerHarris::CornerHarris(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CornerHarris::CornerHarris(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* CornerHarris::transform()
|
|
||||||
{
|
|
||||||
int threshold = getParameter("threshold").toInt();
|
|
||||||
double sigma = getParameter("sigma").toDouble();
|
|
||||||
double sigma_weight = getParameter("sigma_weight").toDouble();
|
|
||||||
double k_param = getParameter("k").toDouble();
|
|
||||||
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
|
|
||||||
math::matrix<float> Ixx(width, height);
|
|
||||||
math::matrix<float> Iyy(width, height);
|
|
||||||
math::matrix<float> Ixy(width, height);
|
|
||||||
math::matrix<float> corner_candidates(width, height);
|
|
||||||
math::matrix<float> corner_nonmax_suppress(width, height);
|
|
||||||
|
|
||||||
ConversionGrayscale* conversion_grayscale = new ConversionGrayscale(image);
|
|
||||||
PNM* gray_image = conversion_grayscale->transform();
|
|
||||||
|
|
||||||
BlurGaussian* blur_gaussian = new BlurGaussian(gray_image);
|
|
||||||
blur_gaussian->setParameter("size", 3);
|
|
||||||
blur_gaussian->setParameter("sigma", 1.6);
|
|
||||||
PNM* blur_gauss_image = blur_gaussian->transform();
|
|
||||||
|
|
||||||
EdgeSobel* edge_sobel = new EdgeSobel(blur_gauss_image);
|
|
||||||
math::matrix<float>* Gx = edge_sobel->rawHorizontalDetection();
|
|
||||||
math::matrix<float>* Gy = edge_sobel->rawVerticalDetection();
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
Ixx[i][j] = (*Gx)[i][j] * (*Gx)[i][j];
|
|
||||||
Ixy[i][j] = (*Gx)[i][j] * (*Gy)[i][j];
|
|
||||||
Iyy[i][j] = (*Gy)[i][j] * (*Gy)[i][j];
|
|
||||||
|
|
||||||
corner_candidates[i][j] = 0;
|
|
||||||
corner_nonmax_suppress[i][j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < width - 1; i++)
|
|
||||||
{
|
|
||||||
for (int j = 1; j < height - 1; j++)
|
|
||||||
{
|
|
||||||
float Sxx = 0;
|
|
||||||
float Syy = 0;
|
|
||||||
float Sxy = 0;
|
|
||||||
|
|
||||||
for (int k = -1; k <= 1; k++)
|
|
||||||
{
|
|
||||||
for (int l = -1; l <= 1; l++)
|
|
||||||
{
|
|
||||||
Sxx = Sxx + Ixx[i + k][j + l] * BlurGaussian::getGauss(k, l, sigma);
|
|
||||||
Syy = Syy + Iyy[i + k][j + l] * BlurGaussian::getGauss(k, l, sigma);
|
|
||||||
Sxy = Sxy + Ixy[i + k][j + l] * BlurGaussian::getGauss(k, l, sigma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Sxx = Sxx / sigma_weight;
|
|
||||||
Sxy = Sxy / sigma_weight;
|
|
||||||
Syy = Syy / sigma_weight;
|
|
||||||
|
|
||||||
math::matrix<float> H(2,2);
|
|
||||||
|
|
||||||
H(0,0) = Sxx;
|
|
||||||
H(0,1) = Sxy;
|
|
||||||
H(1,0) = Sxy;
|
|
||||||
H(1,1) = Syy;
|
|
||||||
|
|
||||||
float detH = H(0, 0) * H(1, 1) - H(0, 1) * H(1, 0); //determinant
|
|
||||||
float trH = H(0, 0) + H(1, 1); //trace
|
|
||||||
float r = detH - k_param * pow(trH, 2);
|
|
||||||
|
|
||||||
if (r > threshold)
|
|
||||||
{
|
|
||||||
corner_candidates[i][j] = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool search = true;
|
|
||||||
|
|
||||||
while(search)
|
|
||||||
{
|
|
||||||
search = false;
|
|
||||||
for (int i = 1; i < width - 1; i++)
|
|
||||||
{
|
|
||||||
for (int j = 1; j <height - 1; j++)
|
|
||||||
{
|
|
||||||
float max = corner_candidates[i][j];
|
|
||||||
|
|
||||||
for (int k = -1; k <= 1; k++)
|
|
||||||
{
|
|
||||||
for (int l = -1; l <= 1; l++)
|
|
||||||
{
|
|
||||||
if (max < corner_candidates[i+k][j+l])
|
|
||||||
{
|
|
||||||
max = corner_candidates[i+k][j+l];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (corner_candidates[i][j] == max)
|
|
||||||
{
|
|
||||||
corner_nonmax_suppress[i][j] = corner_candidates[i][j];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (corner_candidates[i][j] > 0)
|
|
||||||
{
|
|
||||||
search = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
corner_nonmax_suppress[i][j] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
corner_candidates = corner_nonmax_suppress;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (corner_candidates[i][j] == 0)
|
|
||||||
{
|
|
||||||
newImage->setPixel(i, j, Qt::color0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
newImage->setPixel(i, j, Qt::color1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 5.4 KiB |
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 13
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 13-ego znajdują się w katalogu ,,13/do_sprawdzenia/cpp/''
|
|
@ -1,162 +0,0 @@
|
|||||||
#include "corner_harris.h"
|
|
||||||
|
|
||||||
#include "blur_gaussian.h"
|
|
||||||
#include "conversion_grayscale.h"
|
|
||||||
#include "edge_sobel.h"
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
CornerHarris::CornerHarris(PNM* img) :
|
|
||||||
Convolution(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CornerHarris::CornerHarris(PNM* img, ImageViewer* iv) :
|
|
||||||
Convolution(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* CornerHarris::transform()
|
|
||||||
{
|
|
||||||
int threshold = getParameter("threshold").toInt();
|
|
||||||
double sigma = getParameter("sigma").toDouble();
|
|
||||||
double sigma_weight = getParameter("sigma_weight").toDouble();
|
|
||||||
double k_param = getParameter("k").toDouble();
|
|
||||||
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Mono);
|
|
||||||
|
|
||||||
math::matrix<float> Ixx(width, height);
|
|
||||||
math::matrix<float> Iyy(width, height);
|
|
||||||
math::matrix<float> Ixy(width, height);
|
|
||||||
|
|
||||||
this->corner_candidates = new math::matrix<float>(width, height);
|
|
||||||
this->corner_nonmax_suppress = new math::matrix<float>(width, height);
|
|
||||||
|
|
||||||
ConversionGrayscale* conversion_grayscale = new ConversionGrayscale(image);
|
|
||||||
PNM* gray_image = conversion_grayscale->transform();
|
|
||||||
|
|
||||||
BlurGaussian* blur_gaussian = new BlurGaussian(gray_image);
|
|
||||||
blur_gaussian->setParameter("size", 3);
|
|
||||||
blur_gaussian->setParameter("sigma", 1.6);
|
|
||||||
PNM* blur_gauss_image = blur_gaussian->transform();
|
|
||||||
|
|
||||||
EdgeSobel* edge_sobel = new EdgeSobel(blur_gauss_image);
|
|
||||||
math::matrix<float>* Gx = edge_sobel->rawHorizontalDetection();
|
|
||||||
math::matrix<float>* Gy = edge_sobel->rawVerticalDetection();
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
Ixx[i][j] = (*Gx)[i][j] * (*Gx)[i][j];
|
|
||||||
Ixy[i][j] = (*Gx)[i][j] * (*Gy)[i][j];
|
|
||||||
Iyy[i][j] = (*Gy)[i][j] * (*Gy)[i][j];
|
|
||||||
|
|
||||||
(*corner_candidates)[i][j] = 0;
|
|
||||||
(*corner_nonmax_suppress)[i][j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 1; i < width - 1; i++)
|
|
||||||
{
|
|
||||||
for (int j = 1; j < height - 1; j++)
|
|
||||||
{
|
|
||||||
float Sxx = 0;
|
|
||||||
float Syy = 0;
|
|
||||||
float Sxy = 0;
|
|
||||||
|
|
||||||
for (int k = -1; k <= 1; k++)
|
|
||||||
{
|
|
||||||
for (int l = -1; l <= 1; l++)
|
|
||||||
{
|
|
||||||
Sxx = Sxx + Ixx[i + k][j + l] * BlurGaussian::getGauss(k, l, sigma);
|
|
||||||
Syy = Syy + Iyy[i + k][j + l] * BlurGaussian::getGauss(k, l, sigma);
|
|
||||||
Sxy = Sxy + Ixy[i + k][j + l] * BlurGaussian::getGauss(k, l, sigma);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Sxx = Sxx / sigma_weight;
|
|
||||||
Sxy = Sxy / sigma_weight;
|
|
||||||
Syy = Syy / sigma_weight;
|
|
||||||
|
|
||||||
math::matrix<float> H(2,2);
|
|
||||||
|
|
||||||
H(0,0) = Sxx;
|
|
||||||
H(0,1) = Sxy;
|
|
||||||
H(1,0) = Sxy;
|
|
||||||
H(1,1) = Syy;
|
|
||||||
|
|
||||||
float detH = H(0, 0) * H(1, 1) - H(0, 1) * H(1, 0); //determinant
|
|
||||||
float trH = H(0, 0) + H(1, 1); //trace
|
|
||||||
float r = detH - k_param * pow(trH, 2);
|
|
||||||
|
|
||||||
if (r > threshold)
|
|
||||||
{
|
|
||||||
(*corner_candidates)[i][j] = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool search = true;
|
|
||||||
|
|
||||||
while(search)
|
|
||||||
{
|
|
||||||
search = false;
|
|
||||||
for (int i = 1; i < width - 1; i++)
|
|
||||||
{
|
|
||||||
for (int j = 1; j <height - 1; j++)
|
|
||||||
{
|
|
||||||
float max = (*corner_candidates)[i][j];
|
|
||||||
|
|
||||||
for (int k = -1; k <= 1; k++)
|
|
||||||
{
|
|
||||||
for (int l = -1; l <= 1; l++)
|
|
||||||
{
|
|
||||||
if (max < (*corner_candidates)[i+k][j+l])
|
|
||||||
{
|
|
||||||
max = (*corner_candidates)[i+k][j+l];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((*corner_candidates)[i][j] == max)
|
|
||||||
{
|
|
||||||
(*corner_nonmax_suppress)[i][j] = (*corner_candidates)[i][j];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if ((*corner_candidates)[i][j] > 0)
|
|
||||||
{
|
|
||||||
search = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
(*corner_nonmax_suppress)[i][j] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
corner_candidates = corner_nonmax_suppress;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if ((*corner_candidates)[i][j] == 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
newImage->setPixel(i, j, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// std::cout << "White corner" << std::endl;
|
|
||||||
newImage->setPixel(i, j, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
|||||||
#include "hough_lines.h"
|
|
||||||
#include "bin_gradient.h"
|
|
||||||
#include "edge_laplacian.h"
|
|
||||||
|
|
||||||
#include "hough.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <Qt>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
HoughLines::HoughLines(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HoughLines::HoughLines(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
PNM* HoughLines::transform()
|
|
||||||
{
|
|
||||||
|
|
||||||
// Cut of value from the image;
|
|
||||||
int threshold = getParameter("threshold").toInt();
|
|
||||||
bool drawWholeLines = getParameter("draw_whole_lines").toBool();
|
|
||||||
int theta_density = 3;
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(image->copy());
|
|
||||||
|
|
||||||
EdgeLaplacian el(image);
|
|
||||||
el.setParameter("size", 3);
|
|
||||||
PNM* image_edge = el.transform();
|
|
||||||
|
|
||||||
PNM* image_bin = BinarizationGradient(image_edge).transform();
|
|
||||||
|
|
||||||
Hough h(image_edge);
|
|
||||||
|
|
||||||
h.setParameter("theta_density", theta_density);
|
|
||||||
h.setParameter("skip_edge_detection", true);
|
|
||||||
PNM* image_hough = h.transform();
|
|
||||||
|
|
||||||
int hough_width = image_hough->width();
|
|
||||||
int hough_height = image_hough->height();
|
|
||||||
|
|
||||||
int width = image_bin->width();
|
|
||||||
int height = image_bin->height();
|
|
||||||
|
|
||||||
qPainter = new QPainter(newImage);
|
|
||||||
qPainter->setPen(Qt::black);
|
|
||||||
|
|
||||||
for (int theta = 0; theta < hough_width; theta++)
|
|
||||||
{
|
|
||||||
for (int rho = 0; rho < hough_height; rho++)
|
|
||||||
{
|
|
||||||
int val = (int) qGray(image_hough->pixel(theta, rho));
|
|
||||||
if (val > threshold)
|
|
||||||
{
|
|
||||||
double rtheta = ((double)theta / 3.0) * M_PI / 180.0;
|
|
||||||
int rrho = rho - hough_height / 2;
|
|
||||||
qPainter->drawLine(0, round(rrho / sin(rtheta)), width - 1, round((rrho - (width - 1) * cos(rtheta)) / sin(rtheta)));
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int counter_pixels = 0;
|
|
||||||
if (!drawWholeLines)
|
|
||||||
{
|
|
||||||
for (int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
QRgb pixel = image_bin->pixel(x, y);
|
|
||||||
|
|
||||||
if (qGray(pixel) == 0)
|
|
||||||
{
|
|
||||||
counter_pixels++;
|
|
||||||
newImage->setPixel(x, y, image->pixel(x, y));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "counter " << counter_pixels << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef HOUGH_LINES_H
|
|
||||||
#define HOUGH_LINES_H
|
|
||||||
|
|
||||||
#include "transformation.h"
|
|
||||||
|
|
||||||
class HoughLines : public Transformation
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
explicit HoughLines(PNM*);
|
|
||||||
explicit HoughLines(PNM*, ImageViewer*);
|
|
||||||
QPainter* qPainter;
|
|
||||||
virtual PNM* transform();
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // HOUGH_LINES_H
|
|
@ -1,195 +0,0 @@
|
|||||||
#include "hough_rectangles.h"
|
|
||||||
|
|
||||||
#include "corner_harris.h"
|
|
||||||
#include "hough_lines.h"
|
|
||||||
|
|
||||||
#include <QLine>
|
|
||||||
#include <QPainter>
|
|
||||||
|
|
||||||
struct RightAngle {
|
|
||||||
QPoint middle;
|
|
||||||
QPoint a;
|
|
||||||
QPoint b;
|
|
||||||
|
|
||||||
inline bool operator==(RightAngle r) {
|
|
||||||
if (r.middle.x() == middle.x() && r.middle.y() == middle.y() &&
|
|
||||||
((r.a.x()==a.x() && r.a.y()== a.y() && r.b.x() == b.x() && r.b.y() == b.y()) ||
|
|
||||||
(r.a.x()==b.x() && r.a.y()== b.y() && r.b.x() == a.x() && r.b.y() == a.y())))
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} ;
|
|
||||||
|
|
||||||
struct Rectangle {
|
|
||||||
QPoint a;
|
|
||||||
QPoint b;
|
|
||||||
QPoint c;
|
|
||||||
QPoint d;
|
|
||||||
} ;
|
|
||||||
|
|
||||||
|
|
||||||
HoughRectangles::HoughRectangles(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
HoughRectangles::HoughRectangles(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* HoughRectangles::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(image->copy());
|
|
||||||
|
|
||||||
CornerHarris* cornerHarris = new CornerHarris(image);
|
|
||||||
cornerHarris->setParameter("threshold", 30000000);
|
|
||||||
cornerHarris->setParameter("sigma", 1.00),
|
|
||||||
cornerHarris->setParameter("sigma_weight", 0.78),
|
|
||||||
cornerHarris->setParameter("k", 0.0500);
|
|
||||||
PNM* cornersImage = cornerHarris->transform();
|
|
||||||
|
|
||||||
HoughLines* houghLines = new HoughLines(image);
|
|
||||||
|
|
||||||
houghLines->setParameter("threshold", 15);
|
|
||||||
houghLines->setParameter("draw_whole_lines", true);
|
|
||||||
PNM* linesImage = houghLines->transform();
|
|
||||||
|
|
||||||
QPainter* qPainter = new QPainter(newImage);
|
|
||||||
QPen* pen = new QPen(Qt::black);
|
|
||||||
pen->setWidth(3);
|
|
||||||
qPainter->setPen(*pen);
|
|
||||||
|
|
||||||
QMap<int, QPoint> cl; //corners on lines
|
|
||||||
|
|
||||||
//look for corners on lines
|
|
||||||
int position = 0;
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (QColor::fromRgb(cornersImage->pixel(i,j)) == Qt::color0)
|
|
||||||
{
|
|
||||||
if (QColor::fromRgb(linesImage->pixel(i,j)) == Qt::color1)
|
|
||||||
{
|
|
||||||
cl.insert(position, QPoint(i,j));
|
|
||||||
position++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int s = cl.size();
|
|
||||||
int points[s][s][s];
|
|
||||||
|
|
||||||
QList<RightAngle> rightAngles;
|
|
||||||
|
|
||||||
//look for 90 degree angles
|
|
||||||
int count= 0;
|
|
||||||
for (int a = 0; a < s; a++)
|
|
||||||
{
|
|
||||||
for (int b = 0; b < s; b++)
|
|
||||||
{
|
|
||||||
for (int c = 0; c < s; c++)
|
|
||||||
{
|
|
||||||
if (a == b || a == c || b == c)
|
|
||||||
{
|
|
||||||
points[a][b][c] = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
double s1 = (cl[b].x() - cl[a].x());
|
|
||||||
double s2 = (cl[b].x() - cl[c].x());
|
|
||||||
double s3 = (cl[b].y() - cl[a].y());
|
|
||||||
double s4 = (cl[b].y() - cl[c].y());
|
|
||||||
|
|
||||||
if (s1*s2 + s3*s4 > -50 && s1*s2 + s3*s4 < 50)
|
|
||||||
{
|
|
||||||
points[a][b][c] = 1;
|
|
||||||
RightAngle ra;
|
|
||||||
ra.a = cl[a];
|
|
||||||
ra.middle = cl[b];
|
|
||||||
ra.b = cl[c];
|
|
||||||
rightAngles.push_back(ra);
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
points[a][b][c] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Rectangle> rectangles;
|
|
||||||
|
|
||||||
|
|
||||||
//match rectangles
|
|
||||||
for (QList<RightAngle>::iterator r = rightAngles.begin(); r != rightAngles.end(); r++)
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
QPoint newPoint1;
|
|
||||||
|
|
||||||
for (QList<RightAngle>::iterator r1 = rightAngles.begin(); r1!=rightAngles.end(); r1++)
|
|
||||||
{
|
|
||||||
if ((*r1).middle.x() == (*r).a.x() && (*r1).middle.y() == (*r).a.y() &&
|
|
||||||
(((*r1).a.x() == (*r).middle.x() && (*r1).a.y() == (*r).middle.y()) ||
|
|
||||||
((*r1).b.x() == (*r).middle.x() && (*r1).b.y() == (*r).middle.y())))
|
|
||||||
{
|
|
||||||
newPoint1 = ((*r1).a.x() == (*r).middle.x()&& (*r1).a.y() == (*r).middle.y() ? (*r1).b : (*r1).a);
|
|
||||||
|
|
||||||
QPoint newPoint2;
|
|
||||||
for (QList<RightAngle>::iterator r2 = rightAngles.begin(); r2!=rightAngles.end();r2++)
|
|
||||||
{
|
|
||||||
if ((*r2).middle.x() == (*r).b.x() && (*r2).middle.y() == (*r).b.y() &&
|
|
||||||
(((*r2).a.x() == (*r).middle.x() && (*r2).a.y() == (*r).middle.y()) ||
|
|
||||||
((*r2).b.x() == (*r).middle.x() && (*r2).b.y() == (*r).middle.y())))
|
|
||||||
{
|
|
||||||
newPoint2 = (((*r2).a.x() == (*r).middle.x() && (*r2).a.y() == (*r).middle.y()) ? (*r2).b : (*r2).a);
|
|
||||||
|
|
||||||
if (newPoint1.x() == newPoint2.x() && newPoint1.y() == newPoint2.y())
|
|
||||||
{
|
|
||||||
Rectangle rect;
|
|
||||||
rect.a = (*r).a;
|
|
||||||
rect.b = (*r).middle;
|
|
||||||
rect.c = (*r).b;
|
|
||||||
rect.d = newPoint1;
|
|
||||||
rectangles.push_back(rect);
|
|
||||||
|
|
||||||
rightAngles.removeAll(*r);
|
|
||||||
rightAngles.removeAll(*r1);
|
|
||||||
rightAngles.removeAll(*r2);
|
|
||||||
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (found)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (QList<Rectangle>::iterator rect = rectangles.begin(); rect != rectangles.end(); rect++)
|
|
||||||
{
|
|
||||||
qPainter->drawLine((*rect).a, (*rect).b);
|
|
||||||
qPainter->drawLine((*rect).b, (*rect).c);
|
|
||||||
qPainter->drawLine((*rect).c, (*rect).d);
|
|
||||||
qPainter->drawLine((*rect).d, (*rect).a);
|
|
||||||
}
|
|
||||||
|
|
||||||
return newImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 9.3 KiB |
@ -1,4 +0,0 @@
|
|||||||
# Rozwiązania laboratoria 14
|
|
||||||
|
|
||||||
Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp''
|
|
||||||
Zmienieone pliki projektu dla zadania 14-ego znajdują się w katalogu ,,14/do_sprawdzenia/cpp/''
|
|
Before Width: | Height: | Size: 496 KiB |
Before Width: | Height: | Size: 394 KiB |
@ -1,289 +0,0 @@
|
|||||||
#include "segmentation.h"
|
|
||||||
|
|
||||||
#include "conversion_grayscale.h"
|
|
||||||
#include "blur_gaussian.h"
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
Segmentation::Segmentation(PNM* img) :
|
|
||||||
Transformation(img)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Segmentation::Segmentation(PNM* img, ImageViewer* iv) :
|
|
||||||
Transformation(img, iv)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QPoint* Segmentation::neighbourhood(QPoint p)
|
|
||||||
{
|
|
||||||
|
|
||||||
return new QPoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
PNM* Segmentation::transform()
|
|
||||||
{
|
|
||||||
int width = image->width();
|
|
||||||
int height = image->height();
|
|
||||||
|
|
||||||
PNM* newImage = new PNM(width, height, QImage::Format_Grayscale8);
|
|
||||||
|
|
||||||
ConversionGrayscale* conversionGrayscale = new ConversionGrayscale(image);
|
|
||||||
PNM* grayImage = conversionGrayscale->transform();
|
|
||||||
|
|
||||||
// matrix with labels
|
|
||||||
math::matrix<int> lab (width, height);
|
|
||||||
// matrix wiht distances
|
|
||||||
math::matrix<int> dist (width, height);
|
|
||||||
|
|
||||||
int current_label = 0;
|
|
||||||
std::queue<QPoint> fifo;
|
|
||||||
|
|
||||||
// Fill matrixes with -1 for lab and 0 for dist
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
lab[i][j] = -1;
|
|
||||||
dist[i][j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create sorted list of gray pixels
|
|
||||||
std::list<int> hSorted;
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
hSorted.push_back(qGray(grayImage->pixel(i, j)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sort and remove dupliactes of pixels values in queue
|
|
||||||
hSorted.sort();
|
|
||||||
hSorted.unique();
|
|
||||||
|
|
||||||
// Set current distance on 0
|
|
||||||
int current_distance = 0;
|
|
||||||
|
|
||||||
// Iterate over queue of gray pixels
|
|
||||||
for (std::list<int>::iterator h = hSorted.begin(); h != hSorted.end(); h++)
|
|
||||||
{
|
|
||||||
// Iterate over image
|
|
||||||
for (int p_i = 0; p_i < width; p_i++)
|
|
||||||
{
|
|
||||||
for (int p_j = 0; p_j < height; p_j++)
|
|
||||||
{
|
|
||||||
// Check if the grey pixel from the image is the same as the one from the queue
|
|
||||||
if (qGray(image->pixel(p_i, p_j)) == *h)
|
|
||||||
{
|
|
||||||
// If true set lab in this place on -2
|
|
||||||
lab[p_i][p_j] = -2;
|
|
||||||
|
|
||||||
// Check neighbours -1 0 1 left-right and up-down for p_i, p_j
|
|
||||||
for (int x = -1; x < 2; x++)
|
|
||||||
{
|
|
||||||
for (int y = -1; y < 2; y++)
|
|
||||||
{
|
|
||||||
// Check if is not center
|
|
||||||
if (x != 0 || y != 0)
|
|
||||||
{
|
|
||||||
// Create q_i and q_j
|
|
||||||
int q_i = p_i+x;
|
|
||||||
int q_j = p_j+y;
|
|
||||||
|
|
||||||
// Check that the values(q_i, q_j) are within the image dimensions
|
|
||||||
if (q_i >= 0 && q_j >= 0 && q_i < width && q_j < height)
|
|
||||||
{
|
|
||||||
// Check point value lab[q_i][q_j] is greater than or equal to zero
|
|
||||||
if (lab[q_i][q_j] >= 0)
|
|
||||||
{
|
|
||||||
// Initialize queue with neighbours at level h
|
|
||||||
// of current basins or watersheds
|
|
||||||
dist[p_i][p_j] = 1;
|
|
||||||
fifo.push(QPoint(p_i, p_j));
|
|
||||||
} //end if - Check point value lab[q_i][q_j] is greater than or equal to zero
|
|
||||||
} // end if - Check that the values(q_i, q_j) are within the image dimensions
|
|
||||||
} // end if - Check if is not center
|
|
||||||
} //end for
|
|
||||||
} // end for - Check neighbours -1 0 1 left-right and up-down for p_i, p_j
|
|
||||||
} // end if - Check if the grey pixel from the image is the same as the one from the queue
|
|
||||||
} // end for
|
|
||||||
} //end for - Iterate over image
|
|
||||||
|
|
||||||
// Set current distance on 1
|
|
||||||
current_distance = 1;
|
|
||||||
fifo.push(QPoint(-1, -1));
|
|
||||||
|
|
||||||
// while loop
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
// Get first element and remove from queue
|
|
||||||
QPoint p = fifo.front();
|
|
||||||
fifo.pop();
|
|
||||||
|
|
||||||
// Check if x and y equal -1
|
|
||||||
if (p.x() == -1 && p.y() == -1)
|
|
||||||
{
|
|
||||||
// Check ff queue is empty - break loop
|
|
||||||
if (fifo.empty())
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Push to queue Point(-1, -1)
|
|
||||||
fifo.push(QPoint(-1, -1));
|
|
||||||
|
|
||||||
// Increment current distanece
|
|
||||||
current_distance += 1;
|
|
||||||
|
|
||||||
// Get first element and remove from queue
|
|
||||||
p = fifo.front();
|
|
||||||
fifo.pop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check neighbours -1 0 1 left-right and up-down for p_i, p_j
|
|
||||||
for (int x = -1; x < 2; x++)
|
|
||||||
{
|
|
||||||
for (int y = -1; y < 2; y++)
|
|
||||||
{
|
|
||||||
// Check if is not center
|
|
||||||
if (x != 0 || y != 0)
|
|
||||||
{
|
|
||||||
// Get current point x, y values and create q_i, q_j
|
|
||||||
int p_i = p.x();
|
|
||||||
int p_j = p.y();
|
|
||||||
int q_i = p_i + x;
|
|
||||||
int q_j = p_j + y;
|
|
||||||
|
|
||||||
// Check that the values(q_i, q_j) are within the image dimensions
|
|
||||||
if (q_i >= 0 && q_j >= 0 && q_i < width && q_j < height)
|
|
||||||
{
|
|
||||||
// Check distance value of point q_i, q_j is less than current distance and lab[q_i][q_j] is greater than or equal to zero
|
|
||||||
if (dist[q_i][q_j] < current_distance && lab[q_i][q_j] >= 0)
|
|
||||||
{
|
|
||||||
// Check if lab point for q_i and q_j is grather than 0
|
|
||||||
if (lab[q_i][q_j] > 0)
|
|
||||||
{
|
|
||||||
if (lab[p_i][p_j] == -2 or lab[p_i][p_j] == 0)
|
|
||||||
{
|
|
||||||
lab[p_i][p_j] = lab[q_i][q_j];
|
|
||||||
}
|
|
||||||
else if (lab[p_i][p_j] != lab[q_i][q_j])
|
|
||||||
{
|
|
||||||
lab[p_i][p_j] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (lab[p_i][p_j] == -2)
|
|
||||||
{
|
|
||||||
lab[p_i][p_j] = 0;
|
|
||||||
} // end else - Check if lab point for q_i and q_j is grather than 0
|
|
||||||
|
|
||||||
}
|
|
||||||
else if (dist[q_i][q_j] == 0 && lab[q_i][q_j] == -2)
|
|
||||||
{
|
|
||||||
// The q is plateau pixel
|
|
||||||
dist[q_i][q_j] = current_distance + 1;
|
|
||||||
fifo.push(QPoint(q_i, q_j));
|
|
||||||
}
|
|
||||||
} // end if - Check that the values(q_i, q_j) are within the image dimensions
|
|
||||||
} // end if (x != 0 || y != 0)
|
|
||||||
} // end for
|
|
||||||
} // end for - Check neighbours -1 0 1 left-right and up-down for p_i, p_j
|
|
||||||
} // end while
|
|
||||||
|
|
||||||
// Iterate over image - detect and process new minimal at level h
|
|
||||||
for (int p_i = 0; p_i < width; p_i++)
|
|
||||||
{
|
|
||||||
for (int p_j = 0; p_j < height; p_j++)
|
|
||||||
{
|
|
||||||
// Check if the grey pixel from the image is the same as the one from the queue
|
|
||||||
if (qGray(image->pixel(p_i, p_j)) == *h)
|
|
||||||
{
|
|
||||||
// Set distance to zero
|
|
||||||
dist[p_i][p_j] = 0;
|
|
||||||
|
|
||||||
// Check if lab[p_i][p_j] is -2
|
|
||||||
if (lab[p_i][p_j] == -2)
|
|
||||||
{
|
|
||||||
// Increment current lab
|
|
||||||
current_label += 1;
|
|
||||||
// Push point[p_i, p_j] to queue
|
|
||||||
fifo.push(QPoint(p_i, p_j));
|
|
||||||
// Set current lab value to lab[p_i][p_j]
|
|
||||||
lab[p_i][p_j] = current_label;
|
|
||||||
|
|
||||||
// while loop until the queue isn't empty
|
|
||||||
while (!fifo.empty())
|
|
||||||
{
|
|
||||||
QPoint q = fifo.front();
|
|
||||||
fifo.pop();
|
|
||||||
|
|
||||||
// Check neighbours -1 0 1 left-right and up-down for q_i, q_j
|
|
||||||
for (int x = -1; x < 2; x++)
|
|
||||||
{
|
|
||||||
for (int y = -1; y < 2; y++)
|
|
||||||
{
|
|
||||||
if (x != 0 || y != 0)
|
|
||||||
{
|
|
||||||
int q_i = q.x();
|
|
||||||
int q_j = q.y();
|
|
||||||
int r_i = q_i + x;
|
|
||||||
int r_j = q_j + y;
|
|
||||||
if (r_i >= 0 && r_j >= 0 && r_i < width && r_j < height)
|
|
||||||
{
|
|
||||||
if (lab[r_i][r_j] == -2)
|
|
||||||
{
|
|
||||||
fifo.push(QPoint(r_i, r_j));
|
|
||||||
lab[r_i][r_j] = current_label;
|
|
||||||
} // end if set lab[r_i][r_j] == -2
|
|
||||||
|
|
||||||
} // end if (r_i >= 0 && r_j >= 0 && r_i < width && r_j < height)
|
|
||||||
} // end if (x != 0 || y != 0)
|
|
||||||
} // end for inspect neighbours of q
|
|
||||||
} // end for - Check neighbours -1 0 1 left-right and up-down for q_i, q_j
|
|
||||||
} // end while - while loop until the queue isn't empty
|
|
||||||
} // end if - Check if lab[p_i][p_j] is -2
|
|
||||||
} // end if - Check if the grey pixel from the image is the same as the one from the queue
|
|
||||||
} // end for
|
|
||||||
} // end for - Iterate over image - detect and process new minimal at level h
|
|
||||||
} // end for - Iterate over queue of gray pixels
|
|
||||||
|
|
||||||
// Set very small value
|
|
||||||
int max = -100;
|
|
||||||
|
|
||||||
// Get max for lab points
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
if (lab[i][j] > max)
|
|
||||||
{
|
|
||||||
max = lab[i][j];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Protection against division by 0
|
|
||||||
if (max == 0)
|
|
||||||
{
|
|
||||||
max = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw image
|
|
||||||
for (int i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < height; j++)
|
|
||||||
{
|
|
||||||
double pixel = lab[i][j] * 255/max;
|
|
||||||
double r = pixel * 0.3;
|
|
||||||
double g = pixel * 0.6;
|
|
||||||
double b = pixel * 0.1;
|
|
||||||
QColor newPixel = QColor(r+g+b,r+g+b,r+g+b);
|
|
||||||
newImage->setPixel(i, j, QColor(newPixel).rgb());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newImage;
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
P4
|
|
||||||
# CREATOR: GIMP PNM Filter Version 1.1
|
|
||||||
1 1
|
|
||||||
€
|
|
@ -1,4 +0,0 @@
|
|||||||
P4
|
|
||||||
# CREATOR: GIMP PNM Filter Version 1.1
|
|
||||||
5 5
|
|
||||||
€@ @
|
|