Skip to content

Commit

Permalink
Fix infinite loop error.
Browse files Browse the repository at this point in the history
Some refactoring.
  • Loading branch information
Samir55 committed Apr 6, 2018
1 parent 23b6186 commit e5e1aa0
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 34 deletions.
44 changes: 34 additions & 10 deletions src/LineSegmentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
LineSegmentation::LineSegmentation(string path_of_image) {
this->image_path = path_of_image;

// Initialize Sieve ToDo @Samir55.
// Initialize Sieve.
sieve();
}

Expand Down Expand Up @@ -167,7 +167,7 @@ LineSegmentation::get_initial_lines() {
}

void
LineSegmentation::show_lines(string path) {
LineSegmentation::save_image_with_lines(string path) {
cv::Mat img_clone = this->color_img.clone();

for (auto line : initial_lines) {
Expand All @@ -189,6 +189,14 @@ LineSegmentation::show_lines(string path) {
cv::imwrite(path, img_clone);
}

void
LineSegmentation::save_lines_to_file(const vector<cv::Mat> &lines, string path) {
int idx = 0;
for (auto m : lines) {
imwrite(path + "Line " + to_string(idx++) + ".jpg", m);
}
}

void
LineSegmentation::generate_regions() {
// Sort lines by row position.
Expand Down Expand Up @@ -227,19 +235,26 @@ void
LineSegmentation::repair_lines() {
// Loop over the regions.
for (Line *line : initial_lines) {
map<int, bool> column_processed = map<int, bool>();

for (int i = 0; i < line->points.size(); i++) {
Point &point = line->points[i];

int x = (line->points[i]).x, y = (line->points[i]).y;

// Check for vertical line intersection
// In lines, we don't save all the vertical points we save only the start point and the end point.
// So in line->points all we save is the horizontal points so, we know there exists a vertical line by
// comparing the point[i].x (row) with point[i-1].x (row).
if (this->binary_img.at<uchar>(point.x, point.y) == 255) {
if (i == 0) continue;
bool black_found = false;

if (line->points[i - 1].x != line->points[i].x) {
// Means the points are in different rows (a vertical line).
int min_row = min(line->points[i - 1].x, line->points[i].x);
int max_row = max(line->points[i - 1].x, line->points[i].x);

for (int j = min_row; j <= max_row && !black_found; ++j) {
if (this->binary_img.at<uchar>(j, line->points[i - 1].y) == 0) {
x = j, y = line->points[i - 1].y;
Expand All @@ -250,6 +265,12 @@ LineSegmentation::repair_lines() {
if (!black_found) continue;
}

// Ignore it's previously processed
if (column_processed[y]) continue;

// Mark column as processed.
column_processed[y] = true;

for (auto contour : this->contours) {
// Check line & contour intersection
if (y >= contour.tl().x && y <= contour.br().x && x >= contour.tl().y && x <= contour.br().y) {
Expand Down Expand Up @@ -336,15 +357,18 @@ LineSegmentation::segment() {

// Get initial lines.
this->get_initial_lines();
this->show_lines("Initial_Lines.jpg");
this->save_image_with_lines("Initial_Lines.jpg");

// Get initial line regions.
this->generate_regions();

// Repair initial lines and generate the final line regions.
this->repair_lines();

// Generate the final line regions.
this->generate_regions();
this->show_lines("Final_Lines.jpg");

this->save_image_with_lines("Final_Lines.jpg");

return this->get_regions();
}
Expand Down Expand Up @@ -423,14 +447,14 @@ Chunk::find_peaks_valleys(map<int, Valley *> &map_valley) {
this->calculate_histogram();

// Detect Peaks.
for (int i = 1; i + 1< this->histogram.size(); i++) {
int left_val = this->histogram[i - 1], centre_val = this->histogram[i], right_val = this->histogram[i+1];
for (int i = 1; i + 1 < this->histogram.size(); i++) {
int left_val = this->histogram[i - 1], centre_val = this->histogram[i], right_val = this->histogram[i + 1];
if (centre_val >= left_val && centre_val >= right_val) { // Peak detected.
if (!peaks.empty() && i - peaks.back().position <= avg_height/2 &&
if (!peaks.empty() && i - peaks.back().position <= avg_height / 2 &&
centre_val >= peaks.back().value) { // Try to get the largest peak in same region.
peaks.back().position = i;
peaks.back().value = centre_val;
} else if (peaks.size() > 0 && i - peaks.back().position <= avg_height/2 &&
} else if (peaks.size() > 0 && i - peaks.back().position <= avg_height / 2 &&
centre_val < peaks.back().value) {}
else {
peaks.push_back(Peak(i, centre_val));
Expand All @@ -446,11 +470,11 @@ Chunk::find_peaks_valleys(map<int, Valley *> &map_valley) {
peaks_average_values /= max(1, int(peaks.size()));

for (auto peak : peaks) {
if (peak.value >= peaks_average_values/4) {
if (peak.value >= peaks_average_values / 4) {
new_peaks.push_back(peak);
}
}
lines_count = int (new_peaks.size());
lines_count = int(new_peaks.size());
peaks = new_peaks;
// Sort peaks by max value and remove the outliers (the ones with less foreground pixels).
sort(peaks.begin(), peaks.end());
Expand Down
39 changes: 20 additions & 19 deletions src/LineSegmentation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ using namespace cv;
using namespace std;

class LineSegmentation;

class Region;

class Valley;

/// A class representing the separator between line regions.
class Line
{
class Line {
friend class LineSegmentation;

friend class Region;
Expand Down Expand Up @@ -62,16 +63,14 @@ class Line
};

/// A class representing the peaks (local maximum points in the histogram).
class Peak
{
class Peak {
public:
int position;
///< The row position.
int value;
///< The number of foreground pixels.

Peak()
{}
Peak() {}

Peak(int p, int v)
: position(p), value(v)
Expand All @@ -91,8 +90,7 @@ class Peak
};

/// A class representing the valleys (local minimum points in the histogram)
class Valley
{
class Valley {
public:
static int ID;
///< Next available id.
Expand Down Expand Up @@ -120,8 +118,7 @@ class Valley
};

/// A class representing the line regions.
class Region
{
class Region {
friend class LineSegmentation;

private:
Expand Down Expand Up @@ -167,8 +164,7 @@ class Region
};

/// Image Chunk.
class Chunk
{
class Chunk {
friend class LineSegmentation;

/// Valleys and peaks detection in this image chunk.
Expand Down Expand Up @@ -208,14 +204,14 @@ class Chunk
};

/// Line Segmentation class.
class LineSegmentation
{
class LineSegmentation {
private:
bool not_primes_arr[100007];
vector<int> primes;

void
sieve();

void
addPrimesToVector(int, vector<int> &);

Expand All @@ -227,6 +223,11 @@ class LineSegmentation
vector<cv::Mat>
segment();

/// Save current line regions returned from get_regions() or segment() functions in jpg files.
/// \param lines
/// \param path
void save_lines_to_file(const vector<cv::Mat> &lines, string path);

private:
string image_path;
///< Path of the image.
Expand All @@ -236,15 +237,15 @@ class LineSegmentation
///< The grey image.
cv::Mat binary_img;
///< The preprocessed image.
vector<Chunk*> chunks;
vector<Chunk *> chunks;
///< The image chunks.
map<int, Chunk *> chunk_map;
///< Map the Chunk id and its corresponding Chunk pointer
map<int, Valley *> map_valley;
///< Map the Valley id and its corresponding Valley pointer.
vector<Line*> initial_lines;
vector<Line *> initial_lines;
///< The initial lines.
vector<Region*> line_regions;
vector<Region *> line_regions;
///< The regions of all found initial lines in the image.
vector<Rect> contours;
/// The handwritten components found in the binary image.
Expand Down Expand Up @@ -295,13 +296,13 @@ class LineSegmentation
/// Draw the lines on the original color image for debugging.
/// \param path string the path of the output image.
void
show_lines(string path);
save_image_with_lines(string path);

/// Connect the nearest valleys found in image chunks to form an initial line in a recursive manner.
/// This function is called by find_initial_lines.
/// \param i integer The index of the chunk.
/// \param current_valley Valley The current valley.
/// \return Line a candidate(initial line)
Line*
Line *
connect_valleys(int i, Valley *current_valley, Line *line, int valleys_min_abs_dist);
};
8 changes: 3 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ int main(int argc, char *argv[]) {
string img_path = argv[1];
LineSegmentation line_segmentation(img_path);
vector<cv::Mat> lines = line_segmentation.segment();
// ToDo @Samir55 Remove.
int idx = 0;
for(auto m : lines) {
imwrite("Line " + to_string(idx++) + ".jpg", m);
}

// Save lines to path.
line_segmentation.save_lines_to_file(lines, "");
return 0;
}

0 comments on commit e5e1aa0

Please sign in to comment.