33 srcigray(std::move(src)),
36 lxx(std::move(xxdiff)),
37 lyy(std::move(yydiff)),
39 lazydata(std::make_unique<std::mutex>())
46 srcigray(std::move(src)),
50 lazydata(std::make_unique<std::mutex>())
56 static std::tuple<ImageDoubleGray, ImageDoubleGray> derivate1(
const ImageDoubleGray &src)
64 return std::make_tuple(std::move(lx), std::move(ly));
67 static std::tuple<ImageDoubleGray, ImageDoubleGray, ImageDoubleGray, ImageDoubleGray> derivate2(
const ImageDoubleGray &src)
81 return std::make_tuple(std::move(lx), std::move(ly), std::move(lxx), std::move(lyy));
84 static std::tuple<ImageDoubleGray, ImageDoubleGray> derivate1Gauss(
const ImageDoubleGray &src,
double sigma)
87 return derivate1(src);
90 smooth.NormalizeForConvolution();
92 diff1.NormalizeForConvolution();
102 return std::make_tuple(std::move(lx), std::move(ly));
105 static std::tuple<ImageDoubleGray, ImageDoubleGray, ImageDoubleGray, ImageDoubleGray> derivate2Gauss(
const ImageDoubleGray &src,
double sigma)
108 return derivate2(src);
111 smooth.NormalizeForConvolution();
113 diff1.NormalizeForConvolution();
132 return std::make_tuple(std::move(lx), std::move(ly), std::move(lxx), std::move(lyy));
137 for (
auto tmp :
Range(r))
138 r.
At(tmp) += g.
At(tmp) + b.
At(tmp);
144 for (
auto tmp :
Range(r))
151 for (
auto tmp :
Range(i1))
158 for (
auto tmp :
Range(i1))
165 for (
size_t y = 0; y < i.
GetHeight(); ++y)
167 for (
size_t x = i.
GetWidth() - 1; x >= 1; --x)
168 i.
At(x, y) -= i.
At(x - 1, y);
169 i.
At(0, y) = i.
At(1, y);
175 for (
size_t y = 0; y < i.
GetHeight(); ++y)
177 for (
size_t x = 0; x < i.
GetWidth() - 1; ++x)
178 i.
At(x, y) -= i.
At(x + 1, y);
185 for (
size_t y = i.
GetHeight() - 1; y >= 1; --y)
187 for (
size_t x = 0; x < i.
GetWidth(); ++x)
188 i.
At(x, y) -= i.
At(x, y - 1);
190 for (
size_t x = 0; x < i.
GetWidth(); ++x)
191 i.
At(x, 0) = i.
At(x, 1);
196 for (
size_t y = 0; y < i.
GetHeight() - 1; ++y)
198 for (
size_t x = 0; x < i.
GetWidth(); ++x)
199 i.
At(x, y) -= i.
At(x, y + 1);
201 for (
size_t x = 0; x < i.
GetWidth(); ++x)
217 for (
auto tmp :
Range(src))
218 ig.
At(tmp) = src.
At(tmp).r;
219 auto rdiff = derivate1Gauss(ig, sigma);
220 for (
auto tmp :
Range(src))
221 ig.At(tmp) = src.
At(tmp).g;
222 auto gdiff = derivate1Gauss(ig, sigma);
223 for (
auto tmp :
Range(src))
224 ig.At(tmp) = src.
At(tmp).b;
225 auto bdiff = derivate1Gauss(ig, sigma);
227 std::move(absmax(std::get<1>(rdiff), std::get<1>(gdiff), std::get<1>(bdiff))));
232 for (
auto tmp :
Range(src))
233 ig.
At(tmp) = src.
At(tmp).r;
234 auto rdiff = derivate2Gauss(ig, sigma);
235 for (
auto tmp :
Range(src))
236 ig.At(tmp) = src.
At(tmp).g;
237 auto gdiff = derivate2Gauss(ig, sigma);
238 for (
auto tmp :
Range(src))
239 ig.At(tmp) = src.
At(tmp).b;
240 auto bdiff = derivate2Gauss(ig, sigma);
242 std::move(sumrgb(std::get<1>(rdiff), std::get<1>(gdiff), std::get<1>(bdiff))),
243 std::move(sumrgb(std::get<2>(rdiff), std::get<2>(gdiff), std::get<2>(bdiff))),
244 std::move(sumrgb(std::get<3>(rdiff), std::get<3>(gdiff), std::get<3>(bdiff))));
256 for (
auto tmp :
Range(src))
257 irx.
At(tmp) = src.
At(tmp).r;
262 for (
auto tmp :
Range(src))
263 igx.
At(tmp) = src.
At(tmp).g;
268 for (
auto tmp :
Range(src))
269 ibx.
At(tmp) = src.
At(tmp).b;
275 auto& lx = absmax(irx, igx, ibx);
276 auto& ly = absmax(iry, igy, iby);
285 auto& lx = sumrgb(irx, igx, ibx);
286 auto& ly = sumrgb(iry, igy, iby);
302 for (
auto tmp :
Range(src))
303 irx.
At(tmp) = src.
At(tmp).r;
315 for (
auto tmp :
Range(src))
316 igx.
At(tmp) = src.
At(tmp).g;
328 for (
auto tmp :
Range(src))
329 ibx.
At(tmp) = src.
At(tmp).b;
353 for (
auto tmp :
Range(src))
354 irx.
At(tmp) = src.
At(tmp).r;
366 for (
auto tmp :
Range(src))
367 igx.
At(tmp) = src.
At(tmp).g;
379 for (
auto tmp :
Range(src))
380 ibx.
At(tmp) = src.
At(tmp).b;
405 auto diff = derivate2Gauss(src, sigma);
406 return Differential(Downgrade<ImageGray>(src), std::move(std::get<0>(diff)), std::move(std::get<1>(diff)), std::move(std::get<2>(diff)), std::move(std::get<3>(diff)));
423 return Differential(Downgrade<ImageGray>(src), std::move(lx), std::move(ly), std::move(lxx), std::move(lyy));
442 return Differential(Downgrade<ImageGray>(src), std::move(lx), std::move(ly));
461 return Differential(Downgrade<ImageGray>(src), std::move(lx), std::move(ly));
467 void Differential::updateLx2ly2()
469 for (
auto tmp :
Range(lx2ly2))
482 std::lock_guard<std::mutex> l(*lazydata);
483 if (lxx.
Size() != lx.Size())
500 std::lock_guard<std::mutex> l(*lazydata);
519 std::lock_guard<std::mutex> l(*lazydata);
520 if (lxy.
Size() != lx.Size())
538 std::lock_guard<std::mutex> l(*lazydata);
557 for (
auto tmp :
Range(lx2ly2))
558 lw.
At(tmp) = sqrt(lx2ly2.
At(tmp));
571 for (
auto tmp :
Range(lx2ly2))
573 auto n = lx2ly2.
At(tmp);
593 for (
auto tmp :
Range(lx2ly2))
595 double n = lx2ly2.
At(tmp);
615 for (
auto tmp :
Range(lx2ly2))
617 auto n = lx2ly2.
At(tmp);
638 for (
auto tmp :
Range(lx2ly2))
652 for (
auto tmp :
Range(lx2ly2))
654 const auto n = lx2ly2.
At(tmp);
656 tmpimg.At(tmp) /= sqrt(n);
670 for (
auto tmp :
Range(lx2ly2))
672 auto n = lx2ly2.
At(tmp);
674 tmpimg.At(tmp) /= sqrt(n);
688 for (
auto tmp :
Range(lx2ly2))
690 const auto n = lx2ly2.
At(tmp);
692 tmpimg.At(tmp) /= sqrt(n);
706 for (
auto tmp :
Range(lx2ly2))
707 tmpimg.At(tmp) *= lx2ly2.
At(tmp);
720 for (
auto tmp :
Range(lx2ly2))
756 for (
auto i :
Range(img))
758 img.SetMinModule((
int)sqrt(thres));
769 for (
auto tmp :
Range(lx2ly2))
790 for (
auto tmp :
Range(lx2ly2))
811 for (
auto tmp :
Range(lx2ly2))
830 for (
auto tmp :
Range(srcigray))
832 if (srcigray.
At(tmp) > max)
834 max = srcigray.
At(tmp);
837 double S1 = 0, S2 = 0, C1 = 0, C2 = 0;
838 for (
auto tmp :
Range(srcigray))
840 int w1 = srcigray.
At(tmp);
842 S1 += lx2ly2.
At(tmp) * w1;
843 S2 += lx2ly2.
At(tmp) * w2;
850 thres = (m1 + m2) / 2;
871 for (
size_t iter = 0; iter < maxiter; ++iter)
876 for (
size_t y = 1; y < lx.GetHeight() - 1; ++y)
877 for (
size_t x = 1; x < lx.GetWidth() - 1; ++x)
881 cond =
Abs(div.
At(x, y)) < maxdiv;
884 double gx = (1.0/16.0) * (lx.
At(x - 1, y - 1) + lx.
At(x - 1, y + 1) +
885 lx.
At(x + 1, y - 1) + lx.
At(x + 1, y + 1)) +
886 (2.0/16.0) * (lx.
At(x - 1, y) + lx.
At(x + 1, y) +
887 lx.
At(x, y - 1) + lx.
At(x, y + 1)) +
888 (4.0/16.0) * lx.
At(x, y);
889 double gy = (1.0/16.0) * (ly.
At(x - 1, y - 1) + ly.
At(x - 1, y + 1) +
890 ly.
At(x + 1, y - 1) + ly.
At(x + 1, y + 1)) +
891 (2.0/16.0) * (ly.
At(x - 1, y) + ly.
At(x + 1, y) +
892 ly.
At(x, y - 1) + ly.
At(x, y + 1)) +
893 (4.0/16.0) * ly.
At(x, y);
896 lx2ly2.
At(x, y) =
Sqr(gx) +
Sqr(gy);
899 std::swap(lx, tmplx);
900 std::swap(ly, tmply);
916 auto precline = std::vector<Point2DDouble>(w);
917 auto currline = std::vector<Point2DDouble>(w);
918 for (
size_t x = 1; x < w - 1; ++x)
921 precline[x].X =
GetLx().
At(x, 0) / n;
922 precline[x].Y =
GetLy().
At(x, 0) / n;
924 currline[x].X =
GetLx().
At(x, 1) / n;
925 currline[x].Y =
GetLy().
At(x, 1) / n;
927 auto nextline = std::vector<Point2DDouble>(w);
931 for (
size_t x = 1; x < w - 1; ++x)
935 nextline[x].X =
GetLx().
At(x, y + 1) / n;
936 nextline[x].Y =
GetLy().
At(x, y + 1) / n;
939 auto dx =
AbsMaxSameSign(currline[x + 1].Y - currline[x].Y, currline[x].Y - currline[x - 1].Y);
940 auto dy =
AbsMaxSameSign(nextline[x].X - currline[x].X, currline[x].X - precline[x].X);
941 axe.At(x, y) = dx + dy;
944 precline.swap(currline);
945 currline.swap(nextline);
950 static inline double norm(
double a,
double b)
952 return sqrt(
Sqr(a) +
Sqr(b));
968 if ((
Abs(xc) < 0.01) && (
Abs(yc) < 0.01))
970 double g = norm (xc, yc);
971 double g1, g2, g3, g4, xx, yy;
981 g2 = norm(
GetLx().At(j, i-1),
GetLy().At(j, i-1));
982 g4 = norm(
GetLx().At(j, i+1),
GetLy().At(j, i+1));
985 g3 = norm(
GetLx().At(j+1, i+1),
GetLy().At(j+1, i+1));
986 g1 = norm(
GetLx().At(j-1, i-1),
GetLy().At(j-1, i-1));
990 g3 = norm(
GetLx().At(j-1, i+1),
GetLy().At(j-1, i+1));
991 g1 = norm(
GetLx().At(j+1, i-1),
GetLy().At(j+1, i-1));
1001 g2 = norm(
GetLx().At(j+1, i),
GetLy().At(j+1, i));
1002 g4 = norm(
GetLx().At(j-1, i),
GetLy().At(j-1, i));
1005 g3 = norm(
GetLx().At(j-1, i-1),
GetLy().At(j-1, i-1));
1006 g1 = norm(
GetLx().At(j+1, i+1),
GetLy().At(j+1, i+1));
1010 g1 = norm(
GetLx().At(j+1, i-1),
GetLy().At(j+1, i-1));
1011 g3 = norm(
GetLx().At(j-1, i+1),
GetLy().At(j-1, i+1));
1016 if ( (g > (xx*g1 + (yy-xx)*g2)) && (g > (xx*g3 + (yy-xx)*g4)) )
static MatrixDouble NewGaussianLineDerivative(double sigma)
Creates a line matrix with the derivative of a centered Gaussian.
ImageDoubleGray & GetLy() noexcept
Returns a reference to the internal y derivate.
ScalarRange< T > Range(T b, T e)
Creates a range [[b, e[[.
void halfdiffbottom(ImageDoubleGray &i)
ImageDoubleGray MakeCorner()
Returns the corner image.
ImageDoubleGray MakeHessianCorner(double s=0.1)
Returns the Hessian corner image.
T AbsMax(const T &a, const T &b) noexcept(noexcept(Abs(a)))
Returns the value that has the maximal absolute value.
ImageDoubleGray MakeLvv()
Returns the second derivative of the tangent to the isophote.
ImageDoubleGray & GetLx() noexcept
Returns a reference to the internal x derivate.
virtual Matrix & Transpose()
Inplace transposition.
std::vector< pixel_type >::reference At(size_t x, size_t y) noexcept
Returns a reference to a pixel.
ImageDoubleGray MakeLww()
Returns the second derivative of the normal to the isophote.
const ImageDoubleGray & GetLxy()
Returns a reference to the internal xy derivate.
size_t GetHeight() const noexcept
ImageDoubleGray & GetLx2Ly2() noexcept
Returns a reference to the internal first derivatives norm.
static MatrixDouble NewGaussianLineSecondDerivative(double sigma)
Creates a line matrix with the second derivative of a centered Gaussian.
static MatrixDouble NewGaussianLine(double sigma)
Creates a line matrix with a centered Gaussian.
ImageDoubleGray MakeEdge()
Returns the edge image.
void halfdifftop(ImageDoubleGray &i)
ImageDoubleGray MakeIsophoteCurvature()
Returns the isophote curvature image.
ImageDoubleGray MakeKappa2()
Returns the second eigenvalue of the Hessian as an image.
ImageGray MakeCurvature() const
Creates an image representing the curvature of the gradients.
ImageGray MakeImageGray(const ImageRGB &img)
static Differential NewHalfDiffAbsMax(const ImageRGB &src, RGBProjection proj)
AbsMax half derivatives.
ImageDoubleGray MakeDivergence()
Creates the continuous image skeleton.
double AutoThreshold()
Computes the best threshold for lx2ly2.
void NormalizeForConvolution()
Normalizes the matrix to be used for convolution.
static Differential NewHalfDiff(const ImageRGB &src, RGBProjection proj)
Alternate half derivatives.
static Differential NewGaussian(const ImageRGB &src, RGBProjection proj, double sigma)
Convolution with Gaussian derivatives.
const ImageDoubleGray & GetLxx()
Returns a reference to the internal xx derivate.
void halfdiffleft(ImageDoubleGray &i)
Image< double > ImageDoubleGray
double Grayscale image class
constexpr SumType< T > Sqr(const T &v) noexcept(noexcept(v *v))
Returns the square of a value.
const ImageDoubleGray & GetLyx()
Returns a reference to the internal yx derivate.
static Differential NewHalfDiffAbsMin(const ImageRGB &src, RGBProjection proj)
AbsMin half derivatives.
ImageDoubleGray MakeCanny()
Returns Canny's edge detector image.
void Convolve(const MatrixDouble &mat)
Convolution.
Gradient image in polar form.
T AbsMaxSameSign(const T &a, const T &b) noexcept(noexcept(Abs(a))&&noexcept(SignOf(a)))
Returns the value that has the maximal absolute value if the values have the same sign...
Differential(const Differential &)=delete
ImageDoubleGray MakeKappa1()
Returns the first eigenvalue of the Hessian as an image.
void Abs(Image< T > &img, typename std::enable_if< std::is_arithmetic< T >::value >::type *dummy=nullptr) noexcept
Replaces each pixel by its absolute value.
void halfdiffright(ImageDoubleGray &i)
const T & At(size_t pos) const noexcept
T AbsMin(const T &a, const T &b) noexcept(noexcept(Abs(a)))
Returns the value that has the minimal absolute value.
ImageDoubleGray MakeFlowlineCurvature()
Returns the flowline curvature image.
size_t GetWidth() const noexcept
ImageGradient MakeImageGradient()
Returns the gradient image.
ImageDoubleGray MakeGaussianCurvature()
Returns the Gaussian curvature image.
size_t Size() const noexcept
ImageGray MakeGradientCurvature()
Returns the gradient curvature image.
Differential computation on images.
ImageDoubleGray MakeLw()
Returns the derivative of the normal to the isophotes.
ImageDoubleGray MakeLaplacian()
Returns the Laplacian image.
ImageDoubleGray MakeLvw()
Returns the cross derivative of the tangent and normal to the isophote.
void Diffuse(size_t maxiter, double maxdiv=std::numeric_limits< double >::max())
Diffuses the gradient.
ImageDoubleGray MakeGradientModule()
Returns the gradient module image.
const ImageDoubleGray & GetLyy()
Returns a reference to the internal yy derivate.