|
|
|
@ -13,13 +13,34 @@ namespace math { |
|
|
|
using contour = std::vector<cv::Point>; |
|
|
|
constexpr double pi() {return std::atan(1)*4;} |
|
|
|
|
|
|
|
int filter(const cv::Mat& img, cv::Mat output, int seuil) { |
|
|
|
bool detect = false; |
|
|
|
uchar R, G, B; |
|
|
|
int rows = img.rows; |
|
|
|
int cols = img.cols; |
|
|
|
int dim = img.channels(); |
|
|
|
int indexNB; |
|
|
|
|
|
|
|
for (int index=0,indexNB=0;index<dim*rows*cols;index+=dim,indexNB++) { |
|
|
|
detect=0; |
|
|
|
B = img.data[index ]; |
|
|
|
G = img.data[index + 1]; |
|
|
|
R = img.data[index + 2]; |
|
|
|
|
|
|
|
if ((R>G) && (R>B)) |
|
|
|
if (((R-B)>=seuil) || ((R-G)>=seuil)) |
|
|
|
detect=1; |
|
|
|
if (detect==1) |
|
|
|
output.data[indexNB]=255; |
|
|
|
else |
|
|
|
output.data[indexNB]=0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
csignal cont2sig(const contour& cont) { |
|
|
|
csignal sig; |
|
|
|
auto sig_it = sig.begin(); |
|
|
|
auto cont_it = cont.begin(); |
|
|
|
|
|
|
|
for (auto cont_it = cont.begin(); cont_it != cont.end(); ++cont_it) { |
|
|
|
*(sig_it++) = complex((*cont_it).x, (*cont_it).y); |
|
|
|
for (auto p: cont) { |
|
|
|
sig.push_back(complex(p.x, p.y)); |
|
|
|
} |
|
|
|
return sig; |
|
|
|
}; |
|
|
|
@ -35,7 +56,7 @@ namespace math { |
|
|
|
csignal diff(const csignal& input, complex mean) { |
|
|
|
csignal res; |
|
|
|
for (auto x: input) { |
|
|
|
res.push_back(x - mean); |
|
|
|
res.push_back(x-mean); |
|
|
|
} |
|
|
|
return res; |
|
|
|
} |
|
|
|
@ -79,6 +100,8 @@ namespace math { |
|
|
|
int opt_size; |
|
|
|
if (N < input.size()) { |
|
|
|
opt_size = 1 << (int)std::ceil(std::log(input.size())/std::log(2)); |
|
|
|
} else if (N==0){ |
|
|
|
opt_size = input.size(); |
|
|
|
} else { |
|
|
|
opt_size = 1 << (int)std::ceil(std::log(N)/std::log(2)); |
|
|
|
} |
|
|
|
@ -89,30 +112,85 @@ namespace math { |
|
|
|
return fft_rec(sig); |
|
|
|
}; |
|
|
|
|
|
|
|
contour coef2cont(const csignal& tfd, complex mean, int size, int cmax) { |
|
|
|
contour cont; |
|
|
|
auto tf_it = tfd.begin(); |
|
|
|
auto cont_it = cont.begin(); |
|
|
|
int kmin = tfd.size()/2 - cmax; |
|
|
|
int kmax = tfd.size()/2 + cmax; |
|
|
|
void operator*=(csignal& sig, complex& m) { |
|
|
|
for(auto x: sig) { |
|
|
|
x *= m; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void operator*=(csignal& sig, complex&& m) { |
|
|
|
for(auto x: sig) { |
|
|
|
x *= m; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void operator/=(csignal& sig, complex& m) { |
|
|
|
for(auto x: sig) { |
|
|
|
x /= m; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void operator/=(csignal& sig, complex&& m) { |
|
|
|
for(auto x: sig) { |
|
|
|
x /= m; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
for (int m=0; m<tfd.size(); ++m) { |
|
|
|
csignal extract(const csignal& tfd, int cmax) { |
|
|
|
csignal res; |
|
|
|
for (int k=0; k<cmax; ++k) { |
|
|
|
res.push_back(tfd[tfd.size() - cmax + k]); |
|
|
|
} |
|
|
|
for (int k=cmax; k<2*cmax; ++k) { |
|
|
|
res.push_back(tfd[k]); |
|
|
|
} |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
contour sig2cont(const csignal& sig) { |
|
|
|
contour res; |
|
|
|
for (auto x: sig) { |
|
|
|
res.push_back(cv::Point(x.real(), x.imag())); |
|
|
|
} |
|
|
|
return res; |
|
|
|
} |
|
|
|
|
|
|
|
csignal desc2sig(const csignal& desc, complex mean, int N, int kmin) { |
|
|
|
csignal cont; |
|
|
|
auto desc_it = desc.begin(); |
|
|
|
|
|
|
|
for (int m=0; m<N; ++m) { |
|
|
|
complex sum; |
|
|
|
for (int k=kmin; k<kmax; ++k) { |
|
|
|
sum += tfd[k]*std::exp(complex(0, 2*pi()*k*m/tfd.size())); |
|
|
|
for (int k=0; k<desc.size(); ++k) { |
|
|
|
sum += desc[k]*std::exp(complex(0, 2*pi()*(k+kmin)*m/N)); |
|
|
|
} |
|
|
|
complex zm = mean + sum; |
|
|
|
*(cont_it++) = cv::Point(zm.real(), zm.imag()); |
|
|
|
cont.push_back(mean + sum); |
|
|
|
} |
|
|
|
return cont; |
|
|
|
}; |
|
|
|
|
|
|
|
contour simplify_contour(const contour& cont, int cmax) { |
|
|
|
contour res; |
|
|
|
csignal z = cont2sig(cont); |
|
|
|
complex zm = mean(z); |
|
|
|
csignal tfd = fft(diff(z, zm)); |
|
|
|
return coef2cont(tfd, zm, 0, cmax); |
|
|
|
tfd /= tfd.size(); |
|
|
|
csignal desc = extract(tfd, cmax); |
|
|
|
|
|
|
|
if (std::abs(desc[desc.size()-1]) > std::abs(desc[0])) { |
|
|
|
std::reverse(desc.begin(), desc.end()); |
|
|
|
} |
|
|
|
|
|
|
|
double phy = std::arg(desc[desc.size()-1]*desc[0])/2; |
|
|
|
desc *= std::exp(complex(0, -phy)); |
|
|
|
double theta = std::arg(desc[0]); |
|
|
|
|
|
|
|
for (int k=0; k<desc.size(); ++k) { |
|
|
|
desc[k] *= std::exp(complex(0, -theta*k)); |
|
|
|
} |
|
|
|
desc /= desc[0]; |
|
|
|
|
|
|
|
csignal sig = desc2sig(desc, zm, z.size(), cmax); |
|
|
|
return sig2cont(sig); |
|
|
|
}; |
|
|
|
|
|
|
|
int max_cont(const std::vector<contour>& contours) { |
|
|
|
@ -122,7 +200,7 @@ namespace math { |
|
|
|
if (contours[i].size() > max) { |
|
|
|
max = contours[i].size(); |
|
|
|
id = i; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return id; |
|
|
|
}; |
|
|
|
|