This repository has been archived by the owner on Dec 12, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
core.cpp
145 lines (134 loc) · 4.66 KB
/
core.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "core.h"
#include <opencv2/opencv.hpp>
Core::Core() {}
void Core::segmentation()
{
// Initialize seed points
std::vector<std::vector<int>> seeds;
for (int i = s / 2; i < mat.rows; i += s)
{
for (int j = s / 2; j < mat.cols; j += s)
{
seeds.push_back({i, j});
}
}
// Each Pixel's seed number and distance
std::vector<std::vector<std::vector<int>>> pixelInfo;
// Fill the 3d vector
for (int x = 0; x <= mat.rows; x++)
{
std::vector<std::vector<int>> row;
for (int y = 0; y <= mat.cols; y++)
{
// An invalid seed number and maximum distance
row.push_back({-1, INT_MAX});
}
pixelInfo.push_back(row);
}
// Iterate but keep seeds from getting too close
bool changed = true;
for (int iter = 0; iter < s / 2 && changed == true; iter++)
{
changed = false;
// For each seed, from 3x3 pixels around it,
// choose the pixel with the least grad as new seed
for (int i = 0; i < seeds.size(); i++)
{
const std::vector<int> seed = seeds[i];
std::vector<int> seedMin = {-1, -1};
int gradMin = INT_MAX;
const int xstart = std::max(seed[0] - 1, 1);
const int xend = std::min(seed[0] + 1, mat.rows - 1);
for (int x = xstart; x < xend; x++)
{
const int ystart = std::max(seed[1] - 1, 1);
const int yend = std::min(seed[1] + 1, mat.cols - 1);
for (int y = ystart; y < yend; y++)
{
const int grad = gradient({x, y});
if (grad < gradMin)
{
seedMin = {x, y};
gradMin = grad;
}
}
}
// If seed moved
if (seedMin[0] != seeds[i][0] || seedMin[1] != seeds[i][1])
{
seeds[i] = seedMin;
changed = true;
}
}
}
// For each seed, cluster the pixels around it
for (int i = 0; i < seeds.size(); i++)
{
const std::vector<int> seed = seeds[i];
const int xstart = std::max(seed[0] - s, 0);
const int xend = std::min(seed[0] + s, mat.rows);
for (int x = xstart; x < xend; x++)
{
const int ystart = std::max(seed[1] - s, 0);
const int yend = std::min(seed[1] + s, mat.cols);
for (int y = ystart; y < yend; y++)
{
const int d = distance(seed, {x, y});
if (d < pixelInfo[x][y][1])
{
// Assign the pixel to new seed
pixelInfo[x][y] = {i, d};
}
}
}
}
// Paint every pixel
for (int x = 0; x < mat.rows; x++)
{
for (int y = 0; y < mat.cols; y++)
{
const int i = pixelInfo[x][y][0];
// If seed number is valid
if (i >= 0)
{
mat.at<cv::Vec3b>(x, y) = mat.at<cv::Vec3b>(seeds[i][0], seeds[i][1]);
}
else
{
mat.at<cv::Vec3b>(x, y) = {0, 255, 0}; // Green
}
}
}
// Paint the seeds
for (const std::vector<int> &seed : seeds)
{
mat.at<cv::Vec3b>(seed[0], seed[1]) = {0, 0, 0};
}
}
int Core::distance(const std::vector<int> &sxy, const std::vector<int> &pxy)
{
// Color of seed and point
const cv::Vec3b sc = mat.at<cv::Vec3b>(sxy[0], sxy[1]);
const cv::Vec3b pc = mat.at<cv::Vec3b>(pxy[0], pxy[1]);
// Distance of color
const double dc = (abs(sc[0] - pc[0]) + abs(sc[1] - pc[1]) + abs(sc[2] - pc[2])) / 3;
// Distance of space
const double ds = (abs(sxy[0] - pxy[0]) + abs(sxy[1] - pxy[1])) / 2;
// Weighed distance
const int d = (int)(dc * s + ds * m);
return d;
}
int Core::gradient(const std::vector<int> &pxy)
{
// P and the four pixels around it
const cv::Vec3b p = mat.at<cv::Vec3b>(pxy[0], pxy[1]);
const cv::Vec3b xlo = mat.at<cv::Vec3b>(pxy[0] - 1, pxy[1]);
const cv::Vec3b xhi = mat.at<cv::Vec3b>(pxy[0] + 1, pxy[1]);
const cv::Vec3b ylo = mat.at<cv::Vec3b>(pxy[0], pxy[1] - 1);
const cv::Vec3b yhi = mat.at<cv::Vec3b>(pxy[0], pxy[1] + 1);
const int dxhi = abs(xhi[0] - p[0]) + abs(xhi[1] - p[1]) + abs(xhi[2] - p[2]);
const int dxlo = abs(xlo[0] - p[0]) + abs(xlo[1] - p[1]) + abs(xlo[2] - p[2]);
const int dyhi = abs(yhi[0] - p[0]) + abs(yhi[1] - p[1]) + abs(yhi[2] - p[2]);
const int dylo = abs(ylo[0] - p[0]) + abs(ylo[1] - p[1]) + abs(ylo[2] - p[2]);
return dxhi + dxlo + dyhi + dylo;
}