Merge pull request #14109 from PedroFerreiradaCosta:adding_python_version_to_anisotro...
authorPedro Ferreira da Costa <pedro.hpf.costa@gmail.com>
Thu, 21 Mar 2019 19:53:12 +0000 (19:53 +0000)
committerAlexander Alekhin <alexander.a.alekhin@gmail.com>
Thu, 21 Mar 2019 19:53:12 +0000 (22:53 +0300)
* Created python version of the code for the anisotropic image segmentation tutorial. Created python/cpp toggles for the markdown file.

* fix doxygen warnings

doc/tutorials/imgproc/anisotropic_image_segmentation/anisotropic_image_segmentation.markdown
samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py [new file with mode: 0644]

index c05cb63..489cd6b 100755 (executable)
@@ -48,28 +48,65 @@ The orientation of an anisotropic image:
 Coherency:
 \f[C = \frac{\lambda_1 - \lambda_2}{\lambda_1 + \lambda_2}\f]
 
-The coherency ranges from 0 to 1. For ideal local orientation (\f$\lambda_2\f$ = 0, \f$\lambda_1\f$ > 0) it is one, for an isotropic gray value structure (\f$\lambda_1\f$ = \f$\lambda_2\f$ > 0) it is zero.
+The coherency ranges from 0 to 1. For ideal local orientation (\f$\lambda_2\f$ = 0, \f$\lambda_1\f$ > 0) it is one, for an isotropic gray value structure (\f$\lambda_1\f$ = \f$\lambda_2\f$ \> 0) it is zero.
 
 Source code
 -----------
 
 You can find source code in the `samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp` of the OpenCV source code library.
 
-@include cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp
+@add_toggle_cpp
+    @include cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp
+@end_toggle
+
+@add_toggle_python
+    @include samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py
+@end_toggle
 
 Explanation
 -----------
 An anisotropic image segmentation algorithm consists of a gradient structure tensor calculation, an orientation calculation, a coherency calculation and an orientation and coherency thresholding:
-@snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp main
+
+@add_toggle_cpp
+    @snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp main
+@end_toggle
+
+@add_toggle_python
+    @snippet samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py main
+@end_toggle
 
 A function calcGST() calculates orientation and coherency by using a gradient structure tensor. An input parameter w defines a window size:
-@snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp calcGST
+
+@add_toggle_cpp
+    @snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp calcGST
+@end_toggle
+
+@add_toggle_python
+    @snippet samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py calcGST
+@end_toggle
+
 
 The below code applies a thresholds LowThr and HighThr to image orientation and a threshold C_Thr to image coherency calculated by the previous function. LowThr and HighThr define orientation range:
-@snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp thresholding
+
+@add_toggle_cpp
+    @snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp thresholding
+@end_toggle
+
+@add_toggle_python
+    @snippet samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py thresholding
+@end_toggle
+
 
 And finally we combine thresholding results:
-@snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp combining
+
+@add_toggle_cpp
+    @snippet samples/cpp/tutorial_code/ImgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.cpp combining
+@end_toggle
+
+@add_toggle_python
+    @snippet samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py combining
+@end_toggle
+
 
 Result
 ------
diff --git a/samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py b/samples/python/tutorial_code/imgProc/anisotropic_image_segmentation/anisotropic_image_segmentation.py
new file mode 100644 (file)
index 0000000..5e2385a
--- /dev/null
@@ -0,0 +1,92 @@
+
+import cv2 as cv
+import numpy as np
+import argparse
+
+W = 52          # window size is WxW
+C_Thr = 0.43    # threshold for coherency
+LowThr = 35     # threshold1 for orientation, it ranges from 0 to 180
+HighThr = 57    # threshold2 for orientation, it ranges from 0 to 180
+
+## [calcGST]
+## [calcJ_header]
+## [calcGST_proto]
+def calcGST(inputIMG, w):
+## [calcGST_proto]
+    img = inputIMG.astype(np.float32)
+
+    # GST components calculation (start)
+    # J =  (J11 J12; J12 J22) - GST
+    imgDiffX = cv.Sobel(img, cv.CV_32F, 1, 0, 3)
+    imgDiffY = cv.Sobel(img, cv.CV_32F, 0, 1, 3)
+    imgDiffXY = cv.multiply(imgDiffX, imgDiffY)
+    ## [calcJ_header]
+
+    imgDiffXX = cv.multiply(imgDiffX, imgDiffX)
+    imgDiffYY = cv.multiply(imgDiffY, imgDiffY)
+
+    J11 = cv.boxFilter(imgDiffXX, cv.CV_32F, (w,w))
+    J22 = cv.boxFilter(imgDiffYY, cv.CV_32F, (w,w))
+    J12 = cv.boxFilter(imgDiffXY, cv.CV_32F, (w,w))
+    # GST components calculations (stop)
+
+    # eigenvalue calculation (start)
+    # lambda1 = J11 + J22 + sqrt((J11-J22)^2 + 4*J12^2)
+    # lambda2 = J11 + J22 - sqrt((J11-J22)^2 + 4*J12^2)
+    tmp1 = J11 + J22
+    tmp2 = J11 - J22
+    tmp2 = cv.multiply(tmp2, tmp2)
+    tmp3 = cv.multiply(J12, J12)
+    tmp4 = np.sqrt(tmp2 + 4.0 * tmp3)
+
+    lambda1 = tmp1 + tmp4    # biggest eigenvalue
+    lambda2 = tmp1 - tmp4    # smallest eigenvalue
+    # eigenvalue calculation (stop)
+
+    # Coherency calculation (start)
+    # Coherency = (lambda1 - lambda2)/(lambda1 + lambda2)) - measure of anisotropism
+    # Coherency is anisotropy degree (consistency of local orientation)
+    imgCoherencyOut = cv.divide(lambda1 - lambda2, lambda1 + lambda2)
+    # Coherency calculation (stop)
+
+    # orientation angle calculation (start)
+    # tan(2*Alpha) = 2*J12/(J22 - J11)
+    # Alpha = 0.5 atan2(2*J12/(J22 - J11))
+    imgOrientationOut = cv.phase(J22 - J11, 2.0 * J12, angleInDegrees = True)
+    imgOrientationOut = 0.5 * imgOrientationOut
+    # orientation angle calculation (stop)
+
+    return imgCoherencyOut, imgOrientationOut
+## [calcGST]
+
+parser = argparse.ArgumentParser(description='Code for Anisotropic image segmentation tutorial.')
+parser.add_argument('-i', '--input', help='Path to input image.', required=True)
+args = parser.parse_args()
+
+imgIn = cv.imread(args.input, cv.IMREAD_GRAYSCALE)
+if imgIn is None:
+    print('Could not open or find the image: {}'.format(args.input))
+    exit(0)
+
+## [main_extra]
+## [main]
+imgCoherency, imgOrientation = calcGST(imgIn, W)
+
+## [thresholding]
+_, imgCoherencyBin = cv.threshold(imgCoherency, C_Thr, 255, cv.THRESH_BINARY)
+_, imgOrientationBin = cv.threshold(imgOrientation, LowThr, HighThr, cv.THRESH_BINARY)
+## [thresholding]
+
+## [combining]
+imgBin = cv.bitwise_and(imgCoherencyBin, imgOrientationBin)
+## [combining]
+## [main]
+
+imgCoherency = cv.normalize(imgCoherency, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
+imgOrientation = cv.normalize(imgOrientation, None, alpha=0, beta=1, norm_type=cv.NORM_MINMAX, dtype=cv.CV_32F)
+
+cv.imshow('result.jpg', np.uint8(0.5*(imgIn + imgBin)))
+cv.imshow('Coherency.jpg', imgCoherency)
+cv.imshow('Orientation.jpg', imgOrientation)
+cv.waitKey(0)
+## [main_extra]