From 9fc0cabdf556aafae928c51fbc0390e3071be958 Mon Sep 17 00:00:00 2001
From: catree <catree.catreus@outlook.com>
Date: Thu, 17 May 2018 14:19:08 +0200
Subject: [PATCH] Add Java and Python code for trackbar tutorial.

---
 .../highgui/table_of_content_highgui.markdown |   2 +
 .../highgui/trackbar/trackbar.markdown        |  88 ++++++++++---
 .../HighGUI/AddingImagesTrackbar.cpp          |  10 +-
 .../erosion_dilatation/MorphologyDemo1.java   |   8 +-
 .../opening_closing_hats/MorphologyDemo2.java |   8 +-
 .../trackbar/AddingImagesTrackbar.java        | 119 ++++++++++++++++++
 .../highgui/trackbar/AddingImagesTrackbar.py  |  48 +++++++
 7 files changed, 258 insertions(+), 25 deletions(-)
 create mode 100644 samples/java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java
 create mode 100644 samples/python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py

diff --git a/doc/tutorials/highgui/table_of_content_highgui.markdown b/doc/tutorials/highgui/table_of_content_highgui.markdown
index a8f1d4e344..fb5a343664 100644
--- a/doc/tutorials/highgui/table_of_content_highgui.markdown
+++ b/doc/tutorials/highgui/table_of_content_highgui.markdown
@@ -5,6 +5,8 @@ This section contains tutorials about how to use the built-in graphical user int
 
 -   @subpage tutorial_trackbar
 
+    *Languages:* C++, Java, Python
+
     *Compatibility:* \> OpenCV 2.0
 
     *Author:* Ana Huamán
diff --git a/doc/tutorials/highgui/trackbar/trackbar.markdown b/doc/tutorials/highgui/trackbar/trackbar.markdown
index 13898712ab..d6700d6387 100644
--- a/doc/tutorials/highgui/trackbar/trackbar.markdown
+++ b/doc/tutorials/highgui/trackbar/trackbar.markdown
@@ -1,11 +1,11 @@
 Adding a Trackbar to our applications! {#tutorial_trackbar}
 ======================================
 
--   In the previous tutorials (about *linear blending* and the *brightness and contrast
-    adjustments*) you might have noted that we needed to give some **input** to our programs, such
-    as \f$\alpha\f$ and \f$beta\f$. We accomplished that by entering this data using the Terminal
--   Well, it is time to use some fancy GUI tools. OpenCV provides some GUI utilities (*highgui.hpp*)
-    for you. An example of this is a **Trackbar**
+-   In the previous tutorials (about @ref tutorial_adding_images and the @ref tutorial_basic_linear_transform)
+    you might have noted that we needed to give some **input** to our programs, such
+    as \f$\alpha\f$ and \f$beta\f$. We accomplished that by entering this data using the Terminal.
+-   Well, it is time to use some fancy GUI tools. OpenCV provides some GUI utilities (**highgui** module)
+    for you. An example of this is a **Trackbar**.
 
     ![](images/Adding_Trackbars_Tutorial_Trackbar.png)
 
@@ -24,26 +24,73 @@ Code
 
 Let's modify the program made in the tutorial @ref tutorial_adding_images. We will let the user enter the
 \f$\alpha\f$ value by using the Trackbar.
+
+@add_toggle_cpp
 This tutorial code's is shown lines below. You can also download it from
 [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp)
 @include cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp
+@end_toggle
+
+@add_toggle_java
+This tutorial code's is shown lines below. You can also download it from
+[here](https://github.com/opencv/opencv/tree/master/samples/java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java)
+@include java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java
+@end_toggle
+
+@add_toggle_python
+This tutorial code's is shown lines below. You can also download it from
+[here](https://github.com/opencv/opencv/tree/master/samples/python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py)
+@include python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py
+@end_toggle
 
 Explanation
 -----------
 
 We only analyze the code that is related to Trackbar:
 
--#  First, we load two images, which are going to be blended.
-    @snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp load
+-  First, we load two images, which are going to be blended.
+
+@add_toggle_cpp
+@snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp load
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java load
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py load
+@end_toggle
 
--#  To create a trackbar, first we have to create the window in which it is going to be located. So:
-    @snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp window
+-  To create a trackbar, first we have to create the window in which it is going to be located. So:
 
--#  Now we can create the Trackbar:
-    @snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp create_trackbar
+@add_toggle_cpp
+@snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp window
+@end_toggle
 
-    Note the following:
+@add_toggle_java
+@snippet java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java window
+@end_toggle
 
+@add_toggle_python
+@snippet python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py window
+@end_toggle
+
+-  Now we can create the Trackbar:
+
+@add_toggle_cpp
+@snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp create_trackbar
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java create_trackbar
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py create_trackbar
+@end_toggle
+
+Note the following (C++ code):
     -   Our Trackbar has a label **TrackbarName**
     -   The Trackbar is located in the window named **Linear Blend**
     -   The Trackbar values will be in the range from \f$0\f$ to **alpha_slider_max** (the minimum
@@ -51,10 +98,21 @@ We only analyze the code that is related to Trackbar:
     -   The numerical value of Trackbar is stored in **alpha_slider**
     -   Whenever the user moves the Trackbar, the callback function **on_trackbar** is called
 
--#  Finally, we have to define the callback function **on_trackbar**
-    @snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp on_trackbar
+Finally, we have to define the callback function **on_trackbar** for C++ and Python code, using an anonymous inner class listener in Java
+
+@add_toggle_cpp
+@snippet cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp on_trackbar
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java on_trackbar
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py on_trackbar
+@end_toggle
 
-    Note that:
+Note that (C++ code):
     -   We use the value of **alpha_slider** (integer) to get a double value for **alpha**.
     -   **alpha_slider** is updated each time the trackbar is displaced by the user.
     -   We define *src1*, *src2*, *dist*, *alpha*, *alpha_slider* and *beta* as global variables,
diff --git a/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp b/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp
index 51522fa5ca..dce34e7eb4 100644
--- a/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp
+++ b/samples/cpp/tutorial_code/HighGUI/AddingImagesTrackbar.cpp
@@ -6,9 +6,10 @@
 
 #include "opencv2/imgcodecs.hpp"
 #include "opencv2/highgui.hpp"
-#include <stdio.h>
+#include <iostream>
 
 using namespace cv;
+using std::cout;
 
 /** Global Variables */
 const int alpha_slider_max = 100;
@@ -29,11 +30,8 @@ Mat dst;
 static void on_trackbar( int, void* )
 {
    alpha = (double) alpha_slider/alpha_slider_max ;
-
    beta = ( 1.0 - alpha );
-
    addWeighted( src1, alpha, src2, beta, 0.0, dst);
-
    imshow( "Linear Blend", dst );
 }
 //![on_trackbar]
@@ -50,8 +48,8 @@ int main( void )
    src2 = imread("../data/WindowsLogo.jpg");
    //![load]
 
-   if( src1.empty() ) { printf("Error loading src1 \n"); return -1; }
-   if( src2.empty() ) { printf("Error loading src2 \n"); return -1; }
+   if( src1.empty() ) { cout << "Error loading src1 \n"; return -1; }
+   if( src2.empty() ) { cout << "Error loading src2 \n"; return -1; }
 
    /// Initialize values
    alpha_slider = 0;
diff --git a/samples/java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java b/samples/java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java
index 386f94a553..8a52884984 100644
--- a/samples/java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java
+++ b/samples/java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java
@@ -25,7 +25,7 @@ import org.opencv.imgproc.Imgproc;
 public class MorphologyDemo1 {
     private static final String[] ELEMENT_TYPE = { "Rectangle", "Cross", "Ellipse" };
     private static final String[] MORPH_OP = { "Erosion", "Dilatation" };
-    private static int maxKernelSize = 21;
+    private static final int MAX_KERNEL_SIZE = 21;
     private Mat matImgSrc;
     private Mat matImgDst = new Mat();
     private int elementType = Imgproc.CV_SHAPE_RECT;
@@ -83,7 +83,11 @@ public class MorphologyDemo1 {
         sliderPanel.add(elementTypeBox);
 
         sliderPanel.add(new JLabel("Kernel size: 2n + 1"));
-        JSlider slider = new JSlider(0, maxKernelSize, 0);
+        JSlider slider = new JSlider(0, MAX_KERNEL_SIZE, 0);
+        slider.setMajorTickSpacing(5);
+        slider.setMinorTickSpacing(5);
+        slider.setPaintTicks(true);
+        slider.setPaintLabels(true);
         slider.addChangeListener(new ChangeListener() {
             @Override
             public void stateChanged(ChangeEvent e) {
diff --git a/samples/java/tutorial_code/ImgProc/opening_closing_hats/MorphologyDemo2.java b/samples/java/tutorial_code/ImgProc/opening_closing_hats/MorphologyDemo2.java
index e5d80280a9..07d2f6e44d 100644
--- a/samples/java/tutorial_code/ImgProc/opening_closing_hats/MorphologyDemo2.java
+++ b/samples/java/tutorial_code/ImgProc/opening_closing_hats/MorphologyDemo2.java
@@ -27,7 +27,7 @@ public class MorphologyDemo2 {
     private static final int[] MORPH_OP_TYPE = { Imgproc.MORPH_OPEN, Imgproc.MORPH_CLOSE,
             Imgproc.MORPH_GRADIENT, Imgproc.MORPH_TOPHAT, Imgproc.MORPH_BLACKHAT };
     private static final String[] ELEMENT_TYPE = { "Rectangle", "Cross", "Ellipse" };
-    private static int maxKernelSize = 21;
+    private static final int MAX_KERNEL_SIZE = 21;
     private Mat matImgSrc;
     private Mat matImgDst = new Mat();
     private int morphOpType = Imgproc.MORPH_OPEN;
@@ -97,7 +97,11 @@ public class MorphologyDemo2 {
         sliderPanel.add(elementTypeBox);
 
         sliderPanel.add(new JLabel("Kernel size: 2n + 1"));
-        JSlider slider = new JSlider(0, maxKernelSize, 0);
+        JSlider slider = new JSlider(0, MAX_KERNEL_SIZE, 0);
+        slider.setMajorTickSpacing(5);
+        slider.setMinorTickSpacing(5);
+        slider.setPaintTicks(true);
+        slider.setPaintLabels(true);
         slider.addChangeListener(new ChangeListener() {
             @Override
             public void stateChanged(ChangeEvent e) {
diff --git a/samples/java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java b/samples/java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java
new file mode 100644
index 0000000000..5eda2198da
--- /dev/null
+++ b/samples/java/tutorial_code/highgui/trackbar/AddingImagesTrackbar.java
@@ -0,0 +1,119 @@
+import java.awt.BorderLayout;
+import java.awt.Container;
+import java.awt.Image;
+
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSlider;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+
+import org.opencv.core.Core;
+import org.opencv.core.Mat;
+import org.opencv.highgui.HighGui;
+import org.opencv.imgcodecs.Imgcodecs;
+
+public class AddingImagesTrackbar {
+    private static final int ALPHA_SLIDER_MAX = 100;
+    private int alphaVal = 0;
+    private Mat matImgSrc1;
+    private Mat matImgSrc2;
+    private Mat matImgDst = new Mat();
+    private JFrame frame;
+    private JLabel imgLabel;
+
+    public AddingImagesTrackbar(String[] args) {
+        //! [load]
+        String imagePath1 = "../data/LinuxLogo.jpg";
+        String imagePath2 = "../data/WindowsLogo.jpg";
+        if (args.length > 1) {
+            imagePath1 = args[0];
+            imagePath2 = args[1];
+        }
+        matImgSrc1 = Imgcodecs.imread(imagePath1);
+        matImgSrc2 = Imgcodecs.imread(imagePath2);
+        //! [load]
+        if (matImgSrc1.empty()) {
+            System.out.println("Empty image: " + imagePath1);
+            System.exit(0);
+        }
+        if (matImgSrc2.empty()) {
+            System.out.println("Empty image: " + imagePath2);
+            System.exit(0);
+        }
+
+        //! [window]
+        // Create and set up the window.
+        frame = new JFrame("Linear Blend");
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        // Set up the content pane.
+        Image img = HighGui.toBufferedImage(matImgSrc2);
+        addComponentsToPane(frame.getContentPane(), img);
+        // Use the content pane's default BorderLayout. No need for
+        // setLayout(new BorderLayout());
+        // Display the window.
+        frame.pack();
+        frame.setVisible(true);
+        //! [window]
+    }
+
+    private void addComponentsToPane(Container pane, Image img) {
+        if (!(pane.getLayout() instanceof BorderLayout)) {
+            pane.add(new JLabel("Container doesn't use BorderLayout!"));
+            return;
+        }
+
+        JPanel sliderPanel = new JPanel();
+        sliderPanel.setLayout(new BoxLayout(sliderPanel, BoxLayout.PAGE_AXIS));
+
+        //! [create_trackbar]
+        sliderPanel.add(new JLabel(String.format("Alpha x %d", ALPHA_SLIDER_MAX)));
+        JSlider slider = new JSlider(0, ALPHA_SLIDER_MAX, 0);
+        slider.setMajorTickSpacing(20);
+        slider.setMinorTickSpacing(5);
+        slider.setPaintTicks(true);
+        slider.setPaintLabels(true);
+        //! [create_trackbar]
+        //! [on_trackbar]
+        slider.addChangeListener(new ChangeListener() {
+            @Override
+            public void stateChanged(ChangeEvent e) {
+                JSlider source = (JSlider) e.getSource();
+                alphaVal = source.getValue();
+                update();
+            }
+        });
+        //! [on_trackbar]
+        sliderPanel.add(slider);
+
+        pane.add(sliderPanel, BorderLayout.PAGE_START);
+        imgLabel = new JLabel(new ImageIcon(img));
+        pane.add(imgLabel, BorderLayout.CENTER);
+    }
+
+    private void update() {
+        double alpha = alphaVal / (double) ALPHA_SLIDER_MAX;
+        double beta = 1.0 - alpha;
+        Core.addWeighted(matImgSrc1, alpha, matImgSrc2, beta, 0, matImgDst);
+        Image img = HighGui.toBufferedImage(matImgDst);
+        imgLabel.setIcon(new ImageIcon(img));
+        frame.repaint();
+    }
+
+    public static void main(String[] args) {
+        // Load the native OpenCV library
+        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+
+        // Schedule a job for the event dispatch thread:
+        // creating and showing this application's GUI.
+        javax.swing.SwingUtilities.invokeLater(new Runnable() {
+            @Override
+            public void run() {
+                new AddingImagesTrackbar(args);
+            }
+        });
+    }
+}
diff --git a/samples/python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py b/samples/python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py
new file mode 100644
index 0000000000..2ccc978a8e
--- /dev/null
+++ b/samples/python/tutorial_code/highgui/trackbar/AddingImagesTrackbar.py
@@ -0,0 +1,48 @@
+from __future__ import print_function
+from __future__ import division
+import cv2 as cv
+import argparse
+
+alpha_slider_max = 100
+title_window = 'Linear Blend'
+
+## [on_trackbar]
+def on_trackbar(val):
+    alpha = val / alpha_slider_max
+    beta = ( 1.0 - alpha )
+    dst = cv.addWeighted(src1, alpha, src2, beta, 0.0)
+    cv.imshow(title_window, dst)
+## [on_trackbar]
+
+parser = argparse.ArgumentParser(description='Code for Adding a Trackbar to our applications tutorial.')
+parser.add_argument('--input1', help='Path to the first input image.', default='../data/LinuxLogo.jpg')
+parser.add_argument('--input2', help='Path to the second input image.', default='../data/WindowsLogo.jpg')
+args = parser.parse_args()
+
+## [load]
+# Read images ( both have to be of the same size and type )
+src1 = cv.imread(args.input1)
+src2 = cv.imread(args.input2)
+## [load]
+if src1 is None:
+    print('Could not open or find the image: ', args.input1)
+    exit(0)
+
+if src2 is None:
+    print('Could not open or find the image: ', args.input2)
+    exit(0)
+
+## [window]
+cv.namedWindow(title_window)
+## [window]
+
+## [create_trackbar]
+trackbar_name = 'Alpha x %d' % alpha_slider_max
+cv.createTrackbar(trackbar_name, title_window , 0, alpha_slider_max, on_trackbar)
+## [create_trackbar]
+
+# Show some stuff
+on_trackbar(0)
+
+# Wait until user press some key
+cv.waitKey()