1
0
lpo-image-processing/14/do_sprawdzenia/cpp/segmentation.cpp
Jarosław Wieczorek ede4166c9d Zadanie 14
2021-05-21 15:25:12 +02:00

290 lines
11 KiB
C++

#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;
}