Watershed implementation in C++ - c++

I'm working in the watershed algortih in C++. I have implemented a source that i've found but i didn't get the expected results. I obtain:
[
But the result should be this:
[
I have charge the image .bmp into a matrix an then i obtain the Gradient of the image using the Sobel operator.
My wathershed algorith now is:
void Watershed() {
stack<punto> s;
punto p, neighbour;
C_Matrix prueba3 (Gradiente.FirstRow(), Gradiente.LastRow(), Gradiente.FirstCol(), Gradiente.LastCol(), -1);
int auxU, auxV, Eaux, L=1;
for (double g = Gradiente.Min(); g <= Gradiente.Max(); g++) {
for (int i = Gradiente.FirstRow(); i <= Gradiente.LastRow(); i++) {
for (int j = Gradiente.FirstCol(); j <= Gradiente.LastCol(); j++) {
if (Gradiente(i, j) == g) {
p.Guarda(i, j);
s.push(p);
}
while (s.empty() == 0) {
p = s.top();
s.pop();
auxU = p.x;
auxV = p.y;
Eaux = -1;
// 8-connectivity
for (int i = 0; i < 8; i++) {
if (i == 0)
neighbour.Guarda(auxU - 1, auxV - 1);
else if (i == 1)
neighbour.Guarda(auxU, auxV - 1);
else if (i == 2)
neighbour.Guarda(auxU + 1, auxV - 1);
else if (i == 3)
neighbour.Guarda(auxU - 1, auxV);
else if (i == 4)
neighbour.Guarda(auxU + 1, auxV);
else if (i == 5)
neighbour.Guarda(auxU - 1, auxV + 1);
else if (i == 6)
neighbour.Guarda(auxU, auxV + 1);
else
neighbour.Guarda(auxU + 1, auxV + 1);
if (neighbour.x >= Gradiente.FirstRow() && neighbour.x <= Gradiente.LastRow()
&& neighbour.y >= Gradiente.FirstCol() && neighbour.y <= Gradiente.LastCol()) {
if (prueba3(neighbour.x, neighbour.y) > 0) {
if (Eaux == -1) {
Eaux = prueba3(neighbour.x, neighbour.y);
}
else if (prueba3(neighbour.x, neighbour.y) != Eaux)
Eaux = 0;
}
}
}
if (auxU >= Gradiente.FirstRow() && auxU <= Gradiente.LastRow()
&& auxV >= Gradiente.FirstCol() && auxV <= Gradiente.LastCol()) {
if (Eaux >= 0) {
prueba3(auxU, auxV) = Eaux;
}
else {
prueba3(auxU, auxV) = L;
L++;
}
}
else {
C_Print("Se sale");
C_PrintNum("AuxU", auxU);
C_PrintNum("AuxV", auxV);
}
}
}
}
}
C_PrintNum("L = ", L);
double max = prueba3.Max();
if (max > 255.0) {
prueba3.Stretch(0, 255);
}
aux = C_Image(prueba3);
}
I don't know where is the fail, maybe my source has mistakes.

Related

Get co-ordinates surrounding specific matrix

Given an arbitrary matrix, how do I find the co-ordinates that surrounds each city accurately?
E.g. City 1 has surrounding matrix of (0, 0), (0, 3), (1, 0), (1, 3), (2,0), (2, 1), (2, 2), (2, 3).
I have tried using a hardcoded method. Which is loop through each city's co-ordinate, however there are still inaccuracy in this method.
E.g. (0, 1) and from there check all 8 directions, up, down, left, right, upper left, upper right, bottom left, bottom right.
And if the char value is ' ', it is not a city which means it is part of a surrounding.
Is there any way which is much more efficient and more accurate in finding the surrounding?
void surroundings(int x, int y) {
// Initiate the first city struct information
citySummInfo.cityId = cityLocList[0].cityId;
citySummInfo.cityName = cityLocList[0].cityName;
citySummInfoList.push_back(citySummInfo);
// Add unique cityID & cityName into vector
for (size_t i = 0; i < cityLocList.size(); i++) {
for (size_t j = 0; j < citySummInfoList.size(); j++) {
if (cityLocList[i].cityId == citySummInfoList[j].cityId && cityLocList[i].cityName == citySummInfoList[j].cityName) {
break;
}
else if (j == citySummInfoList.size() - 1) {
citySummInfo.cityId = cityLocList[i].cityId;
citySummInfo.cityName = cityLocList[i].cityName;
citySummInfoList.push_back(citySummInfo);
}
}
}
// To populate the entire matrix with city ID
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
for (size_t k = 0; k < cityLocList.size(); k++) {
if (cityLocList[k].xGrid == i && cityLocList[k].yGrid == j)
mapPtr[j][i] = cityLocList[k].cityId + '0';
}
}
}
// Main process of getting the surrounding
for (size_t i = 0; i < citySummInfoList.size(); i++) {
for (size_t j = 0; j < cityLocList.size(); j++) {
if (citySummInfoList[i].cityId == cityLocList[j].cityId)
citySummInfoList[i].coOrdinates.push_back(to_string(cityLocList[j].xGrid) + "." + to_string(cityLocList[j].yGrid));
}
}
for (size_t i = 0; i < citySummInfoList.size(); i++) {
vector<string> temp;
for (size_t j = 0; j < citySummInfoList[i].coOrdinates.size(); j++) {
char cityId = citySummInfoList[i].cityId + '0';
char delim[] = { '.' };
vector<string> tempAxis = tokenizer(citySummInfoList[i].coOrdinates[j], delim, 1);
int xAxis = stoi(tempAxis[0]);
int yAxis = stoi(tempAxis[1]);
if (xAxis - 1 < 0 || yAxis - 1 < 0) {
continue;
}
if (mapPtr[xAxis - 1][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis - 1][yAxis] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis - 1][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis - 1) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis + 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis + 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
if (mapPtr[xAxis + 1][yAxis - 1] != cityId) {
if (xAxis + 1 == x || yAxis + 1 == y || xAxis - 1 < 0 || yAxis - 1 < 0)
continue;
string coOrd = to_string(xAxis + 1) + "." + to_string(yAxis - 1);
if (find(temp.begin(), temp.end(), coOrd) == temp.end()) {
temp.push_back(coOrd);
}
}
}
citySummInfoList[i].coOrdinates.reserve(temp.size());
citySummInfoList[i].coOrdinates.insert(citySummInfoList[i].coOrdinates.end(), temp.begin(), temp.end());
}
}
Also, is there a possibility that my print function may cause such unreliability?
void print(int x, int y) {
for (int i = 0; i <= x + 2; i++) {
if (i == 0 || i >= x + 1) // Indentation for 1st and last row of non city locations
cout << setw(4) << " ";
for (int j = 0; j <= y + 2; j++) {
if ((i == 0 || i == x + 1) && j <= y + 1) { // Layout for first and last row
cout << "# ";
}
else if ((j == 0 && (i != 0 || i <= x))) { // Numbering for each row
if (x - i >= 0) {
cout << setw(3) << left << x - i << " ";
}
else {
cout << " "; // Indentation for last row of #s
}
}
else if (j == 1 && i < x + 2) { // Layout for first column
cout << "#";
}
else if (j == y + 2 && i != 0 && i < x + 1) { // Layout for last column
cout << " #";
}
else if (i == x + 2 && j < y + 1) { // Numbering for each column
cout << j - 1 << " ";
}
else if ((i != 0 && i != x + 2 && j != y + 2)) {
cout << " " << mapPtr[x - i][j - 2]; // Plot map value
}
}
cout << endl;
}
cout << endl;
}
This is an O(n) answer for your problem. The idea behind it is to find all points that are edges (a point is an edge if it is adjacent to anything which is not its own city).
After finding all edge points, loop through each of them and add all points adjacent to them which are whitespace characters.
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int, int> point;
string m[] = {
" ",
" 555 ",
" 555 ",
" 222 555 ",
" 222 ",
" 222 ",
" 222 ",
" ",
"11 33 ",
"11 44",
" 44"
};
//hash function for pairs
struct hash_pair {
template <class T1, class T2>
size_t operator()(const pair<T1, T2>& p) const {
auto hash1 = hash<T1>{}(p.first);
auto hash2 = hash<T2>{}(p.second);
return hash1 ^ hash2;
}
};
bool insideBounds(int x, int y, point &size){
if(x < 0 || x >= size.x || y < 0 || y >= size.y) return false;
return true;
}
bool isEdge(int x, int y, point &size){
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
if(!insideBounds(x + j, y + i, size)) return true;
if(m[y + i][x + j] == ' ') return true;
}
}
return false;
}
void FindSurrounding(int x, int y){
//size of map
point size = make_pair(11, 11);
//current city id
char city = m[y][x];
//finding a point in edge of the city
point edge = make_pair(x, y);
for(int i = x - 1; i >= 0; --i)
if(m[y][i] == city) edge = make_pair(i, y);
//find all edge points
unordered_set<point, hash_pair> visited;
stack<point> toVisit;
toVisit.push(edge);
while(toVisit.size()){
point current = toVisit.top();
visited.insert(current);
toVisit.pop();
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
point p = make_pair(current.x + j, current.y + i);
if(!insideBounds(p.x, p.y, size) || m[p.y][p.x] != city) continue;
if(visited.find(p) == visited.end() && isEdge(p.x, p.y, size)){
toVisit.push(p);
}
}
}
}
//find surrounding slots
unordered_set<point, hash_pair> surrounding;
for (const auto& p: visited) {
for(int i = -1; i < 2; ++i){
for(int j = -1; j < 2; ++j){
point curr = make_pair(p.x + j, p.y + i);
if(insideBounds(curr.x, curr.y, size) && m[curr.y][curr.x] == ' '){
surrounding.insert(curr);
}
}
}
}
//print answer
for (const auto& p: surrounding) {
cout<<"("<<p.x<<", "<<p.y<<"), ";
}
}
int main()
{
FindSurrounding(0, 8);
return 0;
}
OUTPUT: (2, 10), (1, 10), (2, 9), (0, 10), (2, 8), (2, 7), (1, 7), (0, 7),

Google kickstart 2021 L shaped plots cannot understand what is wrong here?

So here is the code I wrote for the question(https://codingcompetitions.withgoogle.com/kickstart/round/0000000000436140/000000000068c509#problem). For the sample input I am getting the right answer but it is not clearing test set 1.
I have created the code such that it checks for "1" up down right and left for each element of array and sees whether from that junction an L can be made.
For reference these are the conditions in the question:
"A segment is called "good" if all the cells in the segment contain only 1s.
An "L-shape" is defined as an unordered pair of segments, which has all the following properties:
Each of the segments must be a "good" segment.
The two segments must be perpendicular to each other.
The segments must share one cell that is an endpoint of both segments.
Segments must have length at least 2.
The length of the longer segment is twice the length of the shorter segment."
#include <bits/stdc++.h>
int main()
{
using namespace std;
int t, u;
cin >> t;
for (u = 1; u <= t; u++) {
int i, j, k, l = 0, a[40][40], r, c, right = 0, left = 0, up = 0, down = 0, downc, upc, lc, rc;
cin >> r >> c;
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
cin >> a[i][j];
}
}
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
if (a[i][j] == 1) {
right = 0;
left = 0;
up = 0;
down = 0;
downc = 0;
upc = 0;
lc = 0;
rc = 0;
for (k = i; k < r; k++) {
if (a[k][j] == 0)
break;
else
down++;
}
for (k = i; k >= 0; k--) {
if (a[k][j] == 0)
break;
else
up++;
}
for (k = j; k < c; k++) {
if (a[i][k] == 0)
break;
else
right++;
}
for (k = j; k >= 0; k--) {
if (a[i][k] == 0)
break;
else
left++;
}
if (!(up > 1 && down > 1 && right > 1 && left > 1)) {
downc = down;
upc = up;
rc = right;
lc = left;
if (up >= 2) {
if (right >= 4) {
while ((upc * 2) > right)
upc--;
l = l + upc - 1;
}
upc = up;
if (left >= 4) {
while ((upc * 2) > left)
upc--;
l = l + upc - 1;
}
upc = up;
}
if (down >= 2) {
if (right >= 4) {
while ((downc * 2) > right)
downc--;
l = l + downc - 1;
}
downc = down;
if (left >= 4) {
while ((downc * 2) > left)
downc--;
l = l + downc - 1;
}
downc = down;
}
if (right >= 2) {
if (up >= 4) {
while ((rc * 2) > up)
rc--;
l = l + rc - 1;
}
rc = right;
if (down >= 4) {
while ((rc * 2) > down)
rc--;
l = l + rc - 1;
}
rc = right;
}
if (left >= 2) {
if (up >= 4) {
while ((lc * 2) > up)
lc--;
l = l + lc - 1;
}
lc = left;
if (down >= 4) {
while ((lc * 2) > down)
lc--;
l = l + lc - 1;
}
lc = left;
}
}
}
}
}
cout << "Case #" << u << ": " << l << "\n";
}
}
Ok so I found the issue finally :
There was no need for " if (!(up > 1 && down > 1 && right > 1 && left > 1)) {.....}"
But still this code is too time consuming to run 1000x1000 grid case. Hence it fails test 2.
Edit: It was a mistake on my end. I bounded the array as 40x40. On changing it to a[1000][1000] it ran both tests successfully. Congos to me.

Tic tac toe Minimax Algorithm Having Weird Behavior (C++)

The other day, I wrote a console game of Tic-Tac-Toe in c++ for my son. He wanted me to add a computer, and I ended us using the minimax algorithm for the first time. I did some quick testing, but really just gave my laptop to my son as soon as it was printing stuff, who played with it for a couple minuets. I looked over his sholder once or twice, and noticed that it wasn't playing optimally, iv'e been trying to debug it, but I can't see where it goes wrong. I tried getting rid of alpha beta prunning, but that did not change anything.
For context, on the board the computer is -1, blank is 0, and the player is 1.
Here is the minimax function:
int minimax(int board[9], int depth, int alpha, int beta, bool isMaxizimaizingPlayer)
{
bool found = false;
for (int i = 0; i < 9; i++)
{
if (board[i] == 0)
{
found = true;
}
}
if (!found)
{
return eval(board);
}
if (depth == 0 || eval(board) != 0)
{
return eval(board);
}
if (isMaxizimaizingPlayer)
{
int maxEval = -2;
for (int spot = 0; spot < 9; spot++)
{
if (board[spot] == 0)
{
board[spot] = 1;
int e = minimax(board, depth - 1, alpha, beta, false);
if (e > maxEval)
{
maxEval = e;
}
//if (beta < alpha)
//{
// break;
//}
board[spot] = 0;
}
}
return maxEval;
}
else {
int minEval = 2;
for (int spot = 0; spot < 9; spot++)
{
if (board[spot] == 0)
{
board[spot] = -1;
int e = minimax(board, depth - 1, alpha, beta, true);
if (e < minEval)
{
minEval = e;
}
//if (beta < alpha)
//{
// break;
//}
board[spot] = 0;
}
}
return minEval;
}
}
To be compleate, here is my eval function:
int eval(int board[9])
{
/*horizontial*/
for (int i = 0; i < 3; i++)
{
if (board[i * 3] == board[i * 3 + 1] && board[i * 3 + 2] == board[i * 3] && board[i * 3] != 0)
{
return board[i * 3];
}
}
/*vertical*/
for (int i = 0; i < 3; i++)
{
if (board[i] == board[i + 3] && board[i] == board[i + 6] && board[i] != 0)
{
return board[i];
}
}
/*Both diags*/
if (board[4] != 0) {
if (board[0] == board[4] && board[0] == board[8])
{
return board[4];
}
if (board[2] == board[4] && board[4] == board[6])
{
return board[4];
}
}
return 0;
}
And here is the inital call:
int spot = 0;
int minEval = 2;
for (int i = 0; i < 9; i++)
{
if (board[i] == 0)
{
board[i] = -1;
int score = minimax(board, 3, -2, 2, false);
if (score < minEval) {
minEval = score;
spot = i;
}
board[i] = 0;
}
}
std::cout << "The computer went in spot " << spot + 1 << std::endl;
board[spot] = -1;
printBoard(board);
It looks like you only call minimax with a depth of three, so the algorithm will only look up to three moves ahead, if you want optimal play you need to set the depth to > 9, so that the agent is always looking ahead to the end of the game.

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

Coin Change Bottom Up Dynamic Programming

http://uva.onlinejudge.org/external/6/674.html I'm trying to solve that problem. Note, though, that it's not the minimum coin change problem, it asks me for the different number of ways to make N cents using 50, 25, 15, 10, 5 and 1 cent coins. It's fairly straightforward, so I made this function:
int count(int n, int m) // n is the N of the problem, m is the number of coin types and s[] is {1, 5, 10, 25, 50}
{
if (n == 0)
{
return 1;
}
if (n < 0)
{
return 0;
}
if (m < 0 && n >= 1)
{
return 0;
}
return DP[n][m - 1] + DP[n - s[m]][m];
}
Fairly straightforward too is adding Dynamic Programming with memoization:
int count(int n, int m)
{
if (n == 0)
{
return 1;
}
if (n < 0)
{
return 0;
}
if (m < 0 && n >= 1)
{
return 0;
}
if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1)
{
return count(n, m - 1) + count(n - s[m], m);
}
else
{
return DP[n][m - 1] + DP[n - s[m]][m];
}
}
However, none of these is fast enough - I need bottom up Dynamic Programming, but I am having difficulties coding it, even with some help from Algorithmist - http://www.algorithmist.com/index.php/Coin_Change.
void generate()
{
for (i = 0; i < MAX; i++)
{
for (u = 0; u < m; u++)
{
if (i == 0)
{
DP[i][u] = 1;
}
else if (u == 0)
{
DP[i][u] = 0;
}
else if (s[u] > i)
{
DP[i][u] = DP[i][u - 1];
}
else
{
DP[i][u] = DP[i][u - 1] + DP[i - s[u]][u];
}
}
}
}
I get 0 for every result for some reason, here's my full code:
#include <stdio.h>
#include <string.h>
using namespace std;
#define MAX 7490
int s[] = {1, 5, 10, 25, 50}, m = 5, input, DP[MAX][5], i, u;
int count(int n, int m)
{
if (n == 0)
{
return 1;
}
if (n < 0)
{
return 0;
}
if (m < 0 && n >= 1)
{
return 0;
}
if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1)
{
return count(n, m - 1) + count(n - s[m], m);
}
else
{
return DP[n][m - 1] + DP[n - s[m]][m];
}
}
void generate()
{
for (i = 0; i < MAX; i++)
{
for (u = 0; u < m; u++)
{
if (i == 0)
{
DP[i][u] = 1;
}
else if (u == 0)
{
DP[i][u] = 0;
}
else if (s[u] > i)
{
DP[i][u] = DP[i][u - 1];
}
else
{
DP[i][u] = DP[i][u - 1] + DP[i - s[u]][u];
}
}
}
}
int main()
{
memset(DP, -1, sizeof DP);
generate();
while (scanf("%d", &input) != EOF)
{
//printf("%d\n", count(input, 4));
printf("%d\n", DP[input][4]);
}
return 0;
}
You did the mistake here:
else if (u == 0)
{
DP[i][u] = 0;
}
It should be DP[i][u]=1 because you can produce any value i using 1 cent coin in 1 possible way. i.e. to take 5 cent you will take 5 one cent coins which is one way to make 5-cent in total.
-----
Btw, in you 1st approach in count method did you have this:
if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1)
{
return count(n, m - 1) + count(n - s[m], m);
}
Or this:
if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1)
{
return DP[n][m] = count(n, m - 1) + count(n - s[m], m);
}
If you did not memoize an already calculated result then this memoization check if (DP[n][m - 1] == -1 || DP[n - s[m]][m] == -1) will never work, which might be the cause of your 1st approach to be too slow :-?