What is the logical difference between these codes? - c++

This is my solution, which receives a heap buffer overflow (out of bounds):
void FFHelper(vector<vector<int>>& image, int i, int j, int newColor, int oldColor)
{
static int m = image.size();
static int n = image[0].size();
if (i < 0 || j < 0
|| i >= m || j >= n
|| image[i][j] != oldColor)
{
return;
}
image[i][j] = newColor;
FFHelper(image, i+1, j, newColor, oldColor);
FFHelper(image, i-1, j, newColor, oldColor);
FFHelper(image, i, j+1, newColor, oldColor);
FFHelper(image, i, j-1, newColor, oldColor);
}
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc, int color)
{
FFHelper(image, sr, sc, color, image[sr][sc]);
return image;
}
where it is guaranteed that 0 <= sr < m and 0 <= sc < n where image is m x n.
This is a code that receives no buffer overflow:
void dfs(vector<vector<int>>& image, int i, int j, int val, int newColor)
{
if(i < 0 || i >= image.size()
|| j < 0 || j>= image[0].size()
|| image[i][j] == newColor || image[i][j] != val)
{
return;
}
image[i][j] = newColor;
dfs(image, i - 1, j, val, newColor);
dfs(image, i + 1, j, val, newColor);
dfs(image, i, j - 1, val, newColor);
dfs(image, i, j + 1, val, newColor);
}
vector<vector<int>> floodFill(vector<vector<int>>& image, int sr, int sc,
int newColor)
{
int val = image[sr][sc];
dfs(image, sr, sc, val, newColor);
return image;
}
What is the difference? I seriously don't see it. Someone from codereview.stackexchange suggested I post here.

Related

Why AddressSanitizer:DEADLYSIGNAL?

class Solution {
int maxRow, maxCol;
int x[4] = {1, -1, 0, 0};
int y[4] = {0, 0, 1, -1};
bool isValid(int row, int col){
return (row >= 0 && row < maxRow && col >= 0 && col < maxCol);
}
int longestPath(int row, int col, vector<vector<int>>& matrix, vector<vector<int>>& dp){
if(dp[row][col] != -1){
return dp[row][col];
}
int longestCurrPath = 1;
for(int dir = 0; dir < 4; ++dir){
int newRow = row + x[dir];
int newCol = col + y[dir];
if(isValid(newRow, newCol) && matrix[col][row] > matrix[newRow][newCol]){
longestCurrPath = max(longestCurrPath, longestPath(newRow, newCol, matrix, dp) + 1);
}
}
return dp[row][col] = longestCurrPath;
}
public:
int longestIncreasingPath(vector<vector<int>>& matrix) {
maxRow = matrix.size();
maxCol = matrix[0].size();
int LIP = 1;
vector<vector<int>> dp(maxRow + 1, vector<int>(maxCol + 1, -1));
for(int row = 0; row < maxRow; ++row){
for(int col = 0; col < maxCol; ++col){
if(dp[row][col] == -1)
LIP = max(LIP, longestPath(row, col, matrix, dp));
}
}
return LIP;
}
};
AddressSanitizer:DEADLYSIGNAL
==31==ERROR: AddressSanitizer: stack-overflow on address 0x7ffe60cafff8 (pc 0x0000003466d2 bp 0x7ffe60cb0070 sp 0x7ffe60cb0000 T0)
==31==ABORTING
Answer: Stackoverflow.
Your recursive logic is buggy. And you perpetually end up in a situation like this:
See comments in the code below
int longestPath(int row, int col, vector<vector<int>>& matrix, vector<vector<int>>& dp){
if(dp[row][col] != -1){
// Termination depends on `dp`
return dp[row][col];
}
int longestCurrPath = 1;
for(int dir = 0; dir < 4; ++dir){
int newRow = row + x[dir];
int newCol = col + y[dir];
if(isValid(newRow, newCol) && matrix[col][row] > matrix[newRow][newCol]) {
// Making recursive calls without ever influencing `dp`
longestCurrPath = max(longestCurrPath, longestPath(newRow, newCol, matrix, dp) + 1);
}
}
// This is the only time you change `dp`
return dp[row][col] = longestCurrPath;
}

Method does not return when it is supposed to and then returns with an incorrect output

In my program, the method findShortestPath should return when i==x and j==y. I've walked through the code and it reaches this point, setting the shortest route to 5 and the route itself to EEENE. However, it continues on and screws with the route before returning an incorrect output of EENESESE.
The Maze im using looks like this:
xxxxx
x...B
A...x
xxxxx
and my code is below:
#include<fstream>
#include<iostream>
#include<string>
#include <vector>
//Maze Size
#define SIZE 5
using namespace std;
bool isSafe(char maze[4][5], int visited[4][5], int x, int y);
bool isValid(int x, int y);
void findShortestPath(char maze[4][5], int visited [4][5], int i, int j, int x, int y, int& min_dist, int dist, string& p_route,string route);
int main()
{
int startRow;
int startColumn;
int endRow;
int endColumn;
int columns = 0;
char maze[4][5];
ifstream input("quickest_route_2.txt");
char data = input.get();
string route;
string p_route;
while (!input.eof())
{
for (int row = 0; row < 4; row++)
{
while (data != '\n' && !input.eof())
{
if (data == 'A')
{
startRow = row;
startColumn = columns;
}
if (data == 'B')
{
endRow = row;
endColumn = columns;
}
maze[row][columns] = data;
columns++;
data = input.get();
}
columns = 0;
data = input.get();
}
}
input.close();
cout << "The Maze being solved is: " << endl;
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 5; x++)
{
cout << maze[y][x];
}
cout << endl;
}
input.close();
// construct a mazerix to keep track of visited cells
int visited[4][5];
// initially all cells are unvisited
memset(visited, 0, sizeof visited);
int min_dist = INT_MAX;
findShortestPath(maze, visited, startRow, startColumn, endRow, endColumn, min_dist, 0,p_route,route);
if (min_dist != INT_MAX)
{
cout << "The shortest path from source to destination has length " << min_dist << endl;
cout << "The route through the maze is: " << p_route << endl;
}
else
cout << "Destination can't be reached from given source";
}
bool isSafe(char maze[4][5], int visited[4][5], int x, int y)
{
if (maze[x][y] == 'x' || visited[x][y] || maze[x][y] == NULL)
return false;
return true;
}
bool isValid(int x, int y)
{
if (x < 4 && y < 5 && x >= 0 && y >= 0)
return true;
return false;
}
void findShortestPath(char maze[4][5], int visited[4][5], int i, int j, int x, int y, int& min_dist, int dist,string&p_route,string route) //I&J Start Point, X&Y End point
{
// if destination is found, update min_dist
if (i == x && j == y)
{
p_route = route;
min_dist = min(dist, min_dist);
return;
}
// set (i, j) cell as visited
visited[i][j] = 1;
// go to bottom cell
if (isValid(i + 1, j) && isSafe(maze, visited, i + 1, j))
findShortestPath(maze, visited, i + 1, j, x, y, min_dist, dist + 1, p_route,route.append("S"));
// go to right cell
if (isValid(i, j + 1) && isSafe(maze, visited, i, j + 1))
findShortestPath(maze, visited, i, j + 1, x, y, min_dist, dist + 1, p_route, route.append("E"));
// go to top cell
if (isValid(i - 1, j) && isSafe(maze, visited, i - 1, j))
findShortestPath(maze, visited, i - 1, j, x, y, min_dist, dist + 1, p_route, route.append("N"));
// go to left cell
if (isValid(i, j - 1) && isSafe(maze, visited, i, j - 1))
findShortestPath(maze, visited, i, j - 1, x, y, min_dist, dist + 1, p_route,route.append("W"));
// Backtrack - Remove (i, j) from visited mazerix
visited[i][j] = 0;
}
Okay, creating and adding a bool solved my issues. I also moved some of my output code from the Main() into findShortestPath
void findShortestPath(char maze[4][5], int visited[4][5], int i, int j, int x, int y, int& min_dist, int dist,string&p_route,string route) //I&J Start Point, X&Y End point
{
bool solved = false;
// if destination is found, update min_dist
while (!solved)
{
if (i == x && j == y)
{
p_route = route;
min_dist = min(dist, min_dist);
if (min_dist != INT_MAX)
{
cout << "The shortest path from source to destination has length " << min_dist << endl;
cout << "The route through the maze is: " << p_route << endl;
}
else
{
cout << "Destination can't be reached from given source";
}
solved = true;
return;
}
// set (i, j) cell as visited
visited[i][j] = 1;
// go to bottom cell
if (isValid(i + 1, j) && isSafe(maze, visited, i + 1, j))
findShortestPath(maze, visited, i + 1, j, x, y, min_dist, dist + 1, p_route, route.append("S"));
// go to right cell
if (isValid(i, j + 1) && isSafe(maze, visited, i, j + 1))
findShortestPath(maze, visited, i, j + 1, x, y, min_dist, dist + 1, p_route, route.append("E"));
// go to top cell
if (isValid(i - 1, j) && isSafe(maze, visited, i - 1, j))
findShortestPath(maze, visited, i - 1, j, x, y, min_dist, dist + 1, p_route, route.append("N"));
// go to left cell
if (isValid(i, j - 1) && isSafe(maze, visited, i, j - 1))
findShortestPath(maze, visited, i, j - 1, x, y, min_dist, dist + 1, p_route, route.append("W"));
// Backtrack - Remove (i, j) from visited mazerix
visited[i][j] = 0;
}
}
Outputs:
The Maze being solved is:
xxxxx
x...B
A...x
xxxxx
The shortest path from source to destination has length 5
The route through the maze is: EEENE

runtime error: reference binding to misaligned address 0xbebebebebebebec6 for type 'int', which requires 4 byte alignment (stl_vector.h)

i am writing code to solve this problem on leetcode
my strategy to solve this is:
run dfs for each cell index (x,y)
on each dfs call check if cell is a destination cell
accordingly set the flags
if both flags are true then add this cell to "ans" vector else carry on with the next dfs
class Solution {
public:
void psUtil(vector<vector<int> >&mat, int x, int y, int m, int n, int &isP, int &isA, vector<vector<int> >&vis, vector<vector<int> >&ans)
{
//check dstinations
if(x == 0 || y == 0)
{
isP = 1;
}
if(x == m || y == n)
{
isA = 1;
}
vector<int> cell(2);
cell[0] = x;
cell[1] = y;
// check both dst rched
if(isA && isP)
{
// append to ans
ans.push_back(cell);
return;
}
// mark vis
vis.push_back(cell);
int X[] = {-1, 0, 1, 0};
int Y[] = {0, 1, 0, -1};
int x1, y1;
// check feasible neighbours
for(int i = 0; i < 4; ++i)
{
x1 = x + X[i];
y1 = y + Y[i];
if(x1 < 0 || y1 < 0) continue;
if(mat[x1][y1] <= mat[x][y])
{
vector<vector<int> > :: iterator it;
vector<int> cell1(2);
cell1[0] = x1;
cell1[1] = y1;
it = find(vis.begin(), vis.end(), cell1);
if(it == vis.end());
else continue;
psUtil(mat, x1, y1, m, n, isP, isA, vis, ans);
if(isA && isP) return;
}
}
}
vector<vector<int>> pacificAtlantic(vector<vector<int>>& matrix)
{
// find dimensions
int m = matrix.size(); // rows
int n = matrix[0].size(); // cols
vector<vector<int> >ans;
// flags if rched destinations
int isP, isA;
isP = isA = 0;
// iterate for all indices
for(int x = 0; x < m; ++x)
{
for(int y = 0; y < n; ++y)
{
// visited nested vector
vector<vector<int> >vis;
psUtil(matrix, x, y, m, n, isP, isA, vis, ans);
isP = isA = 0;
}
}
return ans;
}
};
and my error on running this is
Runtime Error Message:
Line 924: Char 9: runtime error: reference binding to misaligned address 0xbebebebebebebec6 for type 'int', which requires 4 byte alignment (stl_vector.h)
Last executed input:
[[1,2,2,3,5],[3,2,3,4,4],[2,4,5,3,1],[6,7,1,4,5],[5,1,1,2,4]]
why am i getting this message and how do i fix it?
i found my error ! it was because of a missing boundary check for the newly calculated coordinate and improper boundary check for a coordinate in the beginning of psUtil.
instead of this:
if(x == m || y == n)
.
.
.
if(x1 < 0 || y1 < 0) continue;
it should be this:
if(x == m-1 || y == n-1)
.
.
.
if(x1 < 0 || y1 < 0 || x1 >= m || y1 >= n) continue;
Your method is pretty good, but maybe we can improve on the implementation a bit. Here is an accepted solution with a similar DFS method.
class Solution {
public:
int direction_row[4] = {0, 1, -1, 0};
int direction_col[4] = {1, 0, 0, -1};
void depth_first_search(vector<vector<int>> &grid, vector<vector<bool>> &visited, int row, int col, int height) {
if (row < 0 || row > grid.size() - 1 || col < 0 || col > grid[0].size() - 1 || visited[row][col])
return;
if (grid[row][col] < height)
return;
visited[row][col] = true;
for (int iter = 0; iter < 4; iter++)
depth_first_search(grid, visited, row + direction_row[iter], col + direction_col[iter], grid[row][col]);
}
vector<vector<int>> pacificAtlantic(vector<vector<int>> &grid) {
vector<vector<int>> water_flows;
int row_length = grid.size();
if (!row_length)
return water_flows;
int col_length = grid[0].size();
vector<vector<bool>> pacific(row_length, vector<bool>(col_length, false));
vector<vector<bool>> atlantic(row_length, vector<bool>(col_length, false));
for (int row = 0; row < row_length; row++) {
depth_first_search(grid, pacific, row, 0, INT_MIN);
depth_first_search(grid, atlantic, row, col_length - 1, INT_MIN);
}
for (int col = 0; col < col_length; col++) {
depth_first_search(grid, pacific, 0, col, INT_MIN);
depth_first_search(grid, atlantic, row_length - 1, col, INT_MIN);
}
for (int row = 0; row < row_length; row++)
for (int col = 0; col < col_length; col++)
if (pacific[row][col] && atlantic[row][col]) {
water_flows.push_back({row, col});
}
return water_flows;
}
};
I'm not also sure, if this would be the most efficient algorithm for the Pacific Atlantic Water Flow problem. You can check out the discussion board.
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions, explanations, efficient algorithms with a variety of languages, and time/space complexity analysis in there.
417. Pacific Atlantic Water Flow
417. Pacific Atlantic Water Flow - Discussion

Cache Oblivious Matrix Transposition Implementation in C++

I have implemented an in-place cache-oblivious matrix transposition algorithm in C++ as below:
void CacheObliviousTransposition(int x, int delx, int y, int dely, int N, int* matrix) {
if ((delx == 1) && (dely == 1)) {
int tmp = matrix[(N*y) + x];
matrix[(N*y) + x] = matrix[(N*x) + y];
matrix[(N*x) + y] = tmp;
return;
}
if (delx >= dely) {
int xmid = delx / 2;
CacheObliviousTransposition(x, xmid, y, dely, N, matrix);
CacheObliviousTransposition(x + xmid, delx - xmid, y, dely, N, matrix);
return;
}
int ymid = dely / 2;
CacheObliviousTransposition(x, delx, y, ymid, N, matrix);
CacheObliviousTransposition(x, delx, y + ymid, dely - ymid, N, matrix);
}
However, when I called the below method after transposition to ensure that it worked correctly, the if loop is being entered so I'm assuming something must be wrong with the implementation.
void CheckTransposition(int N, int* matrix)
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (matrix[(i*N) + j] != (j*N) + i + 42)
{
cout << "Transposition failed at i=" << i << ", j=" << j << "\n";
}
}
}
}
Can anyone help me identify what is wrong?
Note: variable matrix is a dynamically assigned integer array as below, as matrix is stored row by row in N*N consecutive memory locations
int* MatrixInit(int N)
{
int* matrix = new int[N*N];
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
matrix[(i*N) + j] = (i*N) + j + 42;
}
}
return matrix;
}
The above code will transpose your elements twice. For example, once CacheObliviousTransposition reaches the single element [0,1], it will transpose it with [1,0]. However, a separate recursion will later on reach [1,0], and transpose that with [0,1] again. Ultimately, all elements will be back in their original places.
To ensure that elements are only transposed once, you could check that x is less than y before switching:
void CacheObliviousTransposition(int x, int delx, int y, int dely, int N, int* matrix) {
if ((delx == 1) && (dely == 1)) {
if(x<y)
{
int tmp = matrix[(N*y) + x];
matrix[(N*y) + x] = matrix[(N*x) + y];
matrix[(N*x) + y] = tmp;
}
return;
}
if (delx >= dely) {
int xmid = delx / 2;
CacheObliviousTransposition(x, xmid, y, dely, N, matrix);
CacheObliviousTransposition(x + xmid, delx - xmid, y, dely, N, matrix);
return;
}
int ymid = dely / 2;
CacheObliviousTransposition(x, delx, y, ymid, N, matrix);
CacheObliviousTransposition(x, delx, y + ymid, dely - ymid, N, matrix);
}

Connected Component labeling in OpenCV using recursive algorithm

I'm trying to implement connected component labeling in OpenCV using recursive algorithm. I'm not sure what I have implemented wrongly. the algorithm is like this
B is Binary Image, LB is Labelled Binary Image
procedure connected_component(B,LB)
{
LB:=negate(B);
label:=0;
findComponents(LB,label);
display(LB);
}
procedure findComponents(LB,label)
{
for L:=0 to maxRow
for P:= 0 to maxCol
if LB[L,P] == -1 then
{
label:=label+1;
search(LB,label,L,P);
}
}
procedure search(LB,label,L,P)
{
LB[L,P]:=label;;
Nset:= neighbours(L,P);
for each(L',P') in Nset
{
if(LB[L',P'] == -1) then
search(LB,label,L',P');
}
}
I have written the code in OpenCV as follows
#include<iostream>
#include<opencv2\opencv.hpp>
using namespace cv;
using namespace std;
void findComponents(Mat res, int label);
void search(Mat res, int label, int row, int col);
int main()
{
Mat src = imread("D:/My Library/test/peppers.bmp",0);
src.convertTo(src,CV_8S);
Mat th = src.clone();
threshold(src,th,128,255,CV_8S);
Mat res = th.clone();
for(int i=0;i<res.rows;i++)
for(int j=0;j<res.cols;j++)
res.at<signed char>(i,j) = 0 - th.at<signed char>(i,j);
int label = 0;
findComponents(res,label);
waitKey(0);
return 0;
}
void findComponents(Mat res, int label)
{
for (int i = 1; i < res.rows - 1; i++)
{
for (int j = 1; j < res.cols - 1; j++)
{
if (res.at<signed char>(i, j) == -255)
{
label++;
search(res, label, i, j);
}
}
}
imshow("CC Image", res);
}
void search(Mat res, int label, int row, int col)
{
res.at<signed char>(row, col) = label;
if (res.at<signed char>(row, col + 1) == -255) search(res, label, row, col + 1);
if (res.at<signed char>(row + 1, col + 1) == -255) search(res, label, row+1, col + 1);
if (res.at<signed char>(row + 1, col) == -255) search(res, label, row + 1, col);
if (res.at<signed char>(row + 1, col - 1) == -255) search(res, label, row + 1, col - 1);
else return;
}
The code is does not works. What have I made wrong in implementing the algorithm? I'm new to OpenCV.
You have a few problems in your code. The most important is that you shouldn't use CV_8S matrices. Why?
They have values limited in range [-128, 127]
checking for values equal to -255 won't work correctly
you are limited to at most 127 connected components per image
threshold won't work as expected
maybe others...
I re-implemented your code to correct for these issues:
you should use CV_32S for your labels.
you should account for borders
you can use Mat_<Tp> for easy access, instead of .at<Tp>
Below is the code. I used applyCustomColorMap to better visualize results.
#include <opencv2/opencv.hpp>
#include <algorithm>
#include <vector>
#include <stack>
using namespace cv;
void search(Mat1i& LB, int label, int r, int c)
{
LB(r, c) = label;
// 4 connected
if ((r - 1 > 0) && LB(r - 1, c) == -1) { search(LB, label, r - 1, c ); }
if ((r + 1 < LB.rows) && LB(r + 1, c) == -1) { search(LB, label, r + 1, c ); }
if ((c - 1 > 0) && LB(r, c - 1) == -1) { search(LB, label, r , c - 1); }
if ((c + 1 < LB.cols) && LB(r, c + 1) == -1) { search(LB, label, r , c + 1); }
// 8 connected
if ((r - 1 > 0) && (c - 1 > 0) && LB(r - 1, c - 1) == -1) { search(LB, label, r - 1, c - 1); }
if ((r - 1 > 0) && (c + 1 < LB.cols) && LB(r - 1, c + 1) == -1) { search(LB, label, r - 1, c + 1); }
if ((r + 1 < LB.rows) && (c - 1 > 0) && LB(r + 1, c - 1) == -1) { search(LB, label, r + 1, c - 1); }
if ((r + 1 < LB.rows) && (c + 1 < LB.cols) && LB(r + 1, c + 1) == -1) { search(LB, label, r + 1, c + 1); }
}
int findComponents(Mat1i& LB)
{
int label = 0;
for (int r = 0; r < LB.rows; ++r) {
for (int c = 0; c < LB.cols; ++c) {
if (LB(r, c) == -1) {
++label;
search(LB, label, r, c);
}
}
}
return label;
}
int connected_components(const Mat1b& B, Mat1i& LB)
{
// Foreground is > 0
// Background is 0
LB = Mat1i(B.rows, B.cols, 0);
LB.setTo(-1, B > 0);
// Foreground labels are initialized to -1
// Background labels are initialized to 0
return findComponents(LB);
}
void applyCustomColormap(const Mat1i& src, Mat3b& dst);
int main()
{
// Load grayscale image
Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
// Binarize the image
Mat1b bin;
threshold(img, bin, 127, 255, THRESH_BINARY);
// Find labels
Mat1i labels;
int n_labels = connected_components(bin, labels);
// Show results
Mat3b out;
applyCustomColormap(labels, out);
imshow("Labels", out);
waitKey();
return 0;
}
void applyCustomColormap(const Mat1i& src, Mat3b& dst)
{
// Create JET colormap
double m;
minMaxLoc(src, nullptr, &m);
m++;
int n = ceil(m / 4);
Mat1d u(n * 3 - 1, 1, double(1.0));
for (int i = 1; i <= n; ++i) {
u(i - 1) = double(i) / n;
u((n * 3 - 1) - i) = double(i) / n;
}
std::vector<double> g(n * 3 - 1, 1);
std::vector<double> r(n * 3 - 1, 1);
std::vector<double> b(n * 3 - 1, 1);
for (int i = 0; i < g.size(); ++i)
{
g[i] = ceil(double(n) / 2) - (int(m) % 4 == 1 ? 1 : 0) + i + 1;
r[i] = g[i] + n;
b[i] = g[i] - n;
}
g.erase(std::remove_if(g.begin(), g.end(), [m](double v){ return v > m; }), g.end());
r.erase(std::remove_if(r.begin(), r.end(), [m](double v){ return v > m; }), r.end());
b.erase(std::remove_if(b.begin(), b.end(), [](double v){ return v < 1.0; }), b.end());
Mat1d cmap(m, 3, double(0.0));
for (int i = 0; i < r.size(); ++i) { cmap(int(r[i]) - 1, 0) = u(i); }
for (int i = 0; i < g.size(); ++i) { cmap(int(g[i]) - 1, 1) = u(i); }
for (int i = 0; i < b.size(); ++i) { cmap(int(b[i]) - 1, 2) = u(u.rows - b.size() + i); }
Mat3d cmap3 = cmap.reshape(3);
Mat3b colormap;
cmap3.convertTo(colormap, CV_8U, 255.0);
// Apply color mapping
dst = Mat3b(src.rows, src.cols, Vec3b(0, 0, 0));
for (int r = 0; r < src.rows; ++r)
{
for (int c = 0; c < src.cols; ++c)
{
dst(r, c) = colormap(src(r, c));
}
}
}
Please take care that a recursive implementation is not a good idea for labeling:
it's quite slow
it may fail if you go too deep with recursion, i.e. your components are very big
I suggest to use another algorithm. Here is an implementation of (almost) your algorithm in iterative form. I strongly recommend this one over yours. It can be trivially modified to output the points for each connected component as vector<vector<Point>>, just like cv::findContours would do:
int connected_components2(const Mat1b& img, Mat1i& labels)
{
Mat1b src = img > 0;
labels = Mat1i(img.rows, img.cols, 0);
int label = 0;
int w = src.cols;
int h = src.rows;
int i;
cv::Point point;
for (int y = 0; y<h; y++)
{
for (int x = 0; x<w; x++)
{
if ((src(y, x)) > 0) // Seed found
{
std::stack<int, std::vector<int>> stack2;
i = x + y*w;
stack2.push(i);
// Current component
std::vector<cv::Point> comp;
while (!stack2.empty())
{
i = stack2.top();
stack2.pop();
int x2 = i%w;
int y2 = i / w;
src(y2, x2) = 0;
point.x = x2;
point.y = y2;
comp.push_back(point);
// 4 connected
if (x2 > 0 && (src(y2, x2 - 1) != 0))
{
stack2.push(i - 1);
src(y2, x2 - 1) = 0;
}
if (y2 > 0 && (src(y2 - 1, x2) != 0))
{
stack2.push(i - w);
src(y2 - 1, x2) = 0;
}
if (y2 < h - 1 && (src(y2 + 1, x2) != 0))
{
stack2.push(i + w);
src(y2 + 1, x2) = 0;
}
if (x2 < w - 1 && (src(y2, x2 + 1) != 0))
{
stack2.push(i + 1);
src(y2, x2 + 1) = 0;
}
// 8 connected
if (x2 > 0 && y2 > 0 && (src(y2 - 1, x2 - 1) != 0))
{
stack2.push(i - w - 1);
src(y2 - 1, x2 - 1) = 0;
}
if (x2 > 0 && y2 < h - 1 && (src(y2 + 1, x2 - 1) != 0))
{
stack2.push(i + w - 1);
src(y2 + 1, x2 - 1) = 0;
}
if (x2 < w - 1 && y2>0 && (src(y2 - 1, x2 + 1) != 0))
{
stack2.push(i - w + 1);
src(y2 - 1, x2 + 1) = 0;
}
if (x2 < w - 1 && y2 < h - 1 && (src(y2 + 1, x2 + 1) != 0))
{
stack2.push(i + w + 1);
src(y2 + 1, x2 + 1) = 0;
}
}
++label;
for (int k = 0; k <comp.size(); ++k)
{
labels(comp[k]) = label;
}
}
}
}
return label;
}