Tutorial Basic Geometric Drawing
authortribta <joaocartuchoo@gmail.com>
Fri, 18 Aug 2017 20:33:28 +0000 (21:33 +0100)
committertribta <joaocartuchoo@gmail.com>
Sat, 9 Sep 2017 14:02:51 +0000 (15:02 +0100)
doc/tutorials/core/basic_geometric_drawing/basic_geometric_drawing.markdown
doc/tutorials/core/table_of_content_core.markdown
samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp
samples/java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java [new file with mode: 0644]
samples/python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py [new file with mode: 0644]

index c27e329..ec3a2ff 100644 (file)
@@ -1,19 +1,21 @@
 Basic Drawing {#tutorial_basic_geometric_drawing}
 =============
 
+@prev_tutorial{tutorial_basic_linear_transform}
+@next_tutorial{tutorial_random_generator_and_text}
+
 Goals
 -----
 
 In this tutorial you will learn how to:
 
--   Use @ref cv::Point to define 2D points in an image.
--   Use @ref cv::Scalar and why it is useful
--   Draw a **line** by using the OpenCV function @ref cv::line
--   Draw an **ellipse** by using the OpenCV function @ref cv::ellipse
--   Draw a **rectangle** by using the OpenCV function @ref cv::rectangle
--   Draw a **circle** by using the OpenCV function @ref cv::circle
--   Draw a **filled polygon** by using the OpenCV function @ref cv::fillPoly
+-   Draw a **line** by using the OpenCV function **line()**
+-   Draw an **ellipse** by using the OpenCV function **ellipse()**
+-   Draw a **rectangle** by using the OpenCV function **rectangle()**
+-   Draw a **circle** by using the OpenCV function **circle()**
+-   Draw a **filled polygon** by using the OpenCV function **fillPoly()**
 
+@add_toggle_cpp
 OpenCV Theory
 -------------
 
@@ -42,86 +44,217 @@ Point pt =  Point(10, 8);
     Scalar( a, b, c )
     @endcode
     We would be defining a BGR color such as: *Blue = a*, *Green = b* and *Red = c*
+@end_toggle
+
+@add_toggle_java
+OpenCV Theory
+-------------
+
+For this tutorial, we will heavily use two structures: @ref cv::Point and @ref cv::Scalar :
+
+### Point
+
+It represents a 2D point, specified by its image coordinates \f$x\f$ and \f$y\f$. We can define it as:
+@code{.java}
+Point pt = new Point();
+pt.x = 10;
+pt.y = 8;
+@endcode
+or
+@code{.java}
+Point pt = new Point(10, 8);
+@endcode
+### Scalar
+
+-   Represents a 4-element vector. The type Scalar is widely used in OpenCV for passing pixel
+    values.
+-   In this tutorial, we will use it extensively to represent BGR color values (3 parameters). It is
+    not necessary to define the last argument if it is not going to be used.
+-   Let's see an example, if we are asked for a color argument and we give:
+    @code{.java}
+    Scalar( a, b, c )
+    @endcode
+    We would be defining a BGR color such as: *Blue = a*, *Green = b* and *Red = c*
+@end_toggle
 
 Code
 ----
 
+@add_toggle_cpp
 -   This code is in your OpenCV sample folder. Otherwise you can grab it from
-    [here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp)
+    [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp)
     @include samples/cpp/tutorial_code/core/Matrix/Drawing_1.cpp
+@end_toggle
+
+@add_toggle_java
+-   This code is in your OpenCV sample folder. Otherwise you can grab it from
+    [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java)
+    @include samples/java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java
+@end_toggle
+
+@add_toggle_python
+-   This code is in your OpenCV sample folder. Otherwise you can grab it from
+    [here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py)
+    @include samples/python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py
+@end_toggle
 
 Explanation
 -----------
 
--#  Since we plan to draw two examples (an atom and a rook), we have to create two images and two
-    windows to display them.
-    @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp create_images
-
--#  We created functions to draw different geometric shapes. For instance, to draw the atom we used
-    *MyEllipse* and *MyFilledCircle*:
-    @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp draw_atom
-
--#  And to draw the rook we employed *MyLine*, *rectangle* and a *MyPolygon*:
-    @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp draw_rook
-
--#  Let's check what is inside each of these functions:
-    -   *MyLine*
-        @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp myline
-
-        As we can see, *MyLine* just call the function @ref cv::line , which does the following:
-
-        -   Draw a line from Point **start** to Point **end**
-        -   The line is displayed in the image **img**
-        -   The line color is defined by **Scalar( 0, 0, 0)** which is the RGB value correspondent
-            to **Black**
-        -   The line thickness is set to **thickness** (in this case 2)
-        -   The line is a 8-connected one (**lineType** = 8)
-    -   *MyEllipse*
-        @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp myellipse
-
-        From the code above, we can observe that the function @ref cv::ellipse draws an ellipse such
-        that:
-
-        -   The ellipse is displayed in the image **img**
-        -   The ellipse center is located in the point **(w/2, w/2)** and is enclosed in a box
-            of size **(w/4, w/16)**
-        -   The ellipse is rotated **angle** degrees
-        -   The ellipse extends an arc between **0** and **360** degrees
-        -   The color of the figure will be **Scalar( 255, 0, 0)** which means blue in BGR value.
-        -   The ellipse's **thickness** is 2.
-    -   *MyFilledCircle*
-        @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp myfilledcircle
-
-        Similar to the ellipse function, we can observe that *circle* receives as arguments:
-
-        -   The image where the circle will be displayed (**img**)
-        -   The center of the circle denoted as the Point **center**
-        -   The radius of the circle: **w/32**
-        -   The color of the circle: **Scalar(0, 0, 255)** which means *Red* in BGR
-        -   Since **thickness** = -1, the circle will be drawn filled.
-    -   *MyPolygon*
-        @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp mypolygon
-
-        To draw a filled polygon we use the function @ref cv::fillPoly . We note that:
-
-        -   The polygon will be drawn on **img**
-        -   The vertices of the polygon are the set of points in **ppt**
-        -   The total number of vertices to be drawn are **npt**
-        -   The number of polygons to be drawn is only **1**
-        -   The color of the polygon is defined by **Scalar( 255, 255, 255)**, which is the BGR
-            value for *white*
-    -   *rectangle*
-        @snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp rectangle
-
-        Finally we have the @ref cv::rectangle function (we did not create a special function for
-        this guy). We note that:
-
-        -   The rectangle will be drawn on **rook_image**
-        -   Two opposite vertices of the rectangle are defined by *\* Point( 0, 7*w/8 )*\*
-            andPoint( w, w)*\*
-        -   The color of the rectangle is given by **Scalar(0, 255, 255)** which is the BGR value
-            for *yellow*
-        -   Since the thickness value is given by **FILLED (-1)**, the rectangle will be filled.
+Since we plan to draw two examples (an atom and a rook), we have to create two images and two
+windows to display them.
+@add_toggle_cpp
+@snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp create_images
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java create_images
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py create_images
+@end_toggle
+
+We created functions to draw different geometric shapes. For instance, to draw the atom we used
+**MyEllipse** and **MyFilledCircle**:
+@add_toggle_cpp
+@snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp draw_atom
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java draw_atom
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py draw_atom
+@end_toggle
+
+And to draw the rook we employed **MyLine**, **rectangle** and a **MyPolygon**:
+@add_toggle_cpp
+@snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp draw_rook
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java draw_rook
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py draw_rook
+@end_toggle
+
+
+Let's check what is inside each of these functions:
+@add_toggle_cpp
+@end_toggle
+
+<H4>MyLine</H4>
+@add_toggle_cpp
+@snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp my_line
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java my_line
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py my_line
+@end_toggle
+
+-   As we can see, **MyLine** just call the function **line()** , which does the following:
+    -   Draw a line from Point **start** to Point **end**
+    -   The line is displayed in the image **img**
+    -   The line color is defined by <B>( 0, 0, 0 )</B> which is the RGB value correspondent
+        to **Black**
+    -   The line thickness is set to **thickness** (in this case 2)
+    -   The line is a 8-connected one (**lineType** = 8)
+
+<H4>MyEllipse</H4>
+@add_toggle_cpp
+@snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp my_ellipse
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java my_ellipse
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py my_ellipse
+@end_toggle
+
+-   From the code above, we can observe that the function **ellipse()** draws an ellipse such
+    that:
+
+    -   The ellipse is displayed in the image **img**
+    -   The ellipse center is located in the point <B>(w/2, w/2)</B> and is enclosed in a box
+        of size <B>(w/4, w/16)</B>
+    -   The ellipse is rotated **angle** degrees
+    -   The ellipse extends an arc between **0** and **360** degrees
+    -   The color of the figure will be <B>( 255, 0, 0 )</B> which means blue in BGR value.
+    -   The ellipse's **thickness** is 2.
+
+<H4>MyFilledCircle</H4>
+@add_toggle_cpp
+@snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp my_filled_circle
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java my_filled_circle
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py my_filled_circle
+@end_toggle
+
+-   Similar to the ellipse function, we can observe that *circle* receives as arguments:
+
+    -   The image where the circle will be displayed (**img**)
+    -   The center of the circle denoted as the point **center**
+    -   The radius of the circle: **w/32**
+    -   The color of the circle: <B>( 0, 0, 255 )</B> which means *Red* in BGR
+    -   Since **thickness** = -1, the circle will be drawn filled.
+
+<H4>MyPolygon</H4>
+@add_toggle_cpp
+@snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp my_polygon
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java my_polygon
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py my_polygon
+@end_toggle
+
+-   To draw a filled polygon we use the function **fillPoly()** . We note that:
+
+    -   The polygon will be drawn on **img**
+    -   The vertices of the polygon are the set of points in **ppt**
+    -   The color of the polygon is defined by <B>( 255, 255, 255 )</B>, which is the BGR
+        value for *white*
+
+<H4>rectangle</H4>
+@add_toggle_cpp
+@snippet cpp/tutorial_code/core/Matrix/Drawing_1.cpp rectangle
+@end_toggle
+
+@add_toggle_java
+@snippet java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java rectangle
+@end_toggle
+
+@add_toggle_python
+@snippet python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py rectangle
+@end_toggle
+
+-   Finally we have the @ref cv::rectangle function (we did not create a special function for
+    this guy). We note that:
+
+    -   The rectangle will be drawn on **rook_image**
+    -   Two opposite vertices of the rectangle are defined by <B>( 0, 7*w/8 )</B>
+        and <B>( w, w )</B>
+    -   The color of the rectangle is given by <B>( 0, 255, 255 )</B> which is the BGR value
+        for *yellow*
+    -   Since the thickness value is given by **FILLED (-1)**, the rectangle will be filled.
 
 Result
 ------
index c0453dd..af040b9 100644 (file)
@@ -58,6 +58,8 @@ understanding how to manipulate the images on a pixel level.
 
 -   @subpage tutorial_basic_geometric_drawing
 
+    *Languages:* C++, Java, Python
+
     *Compatibility:* \> OpenCV 2.0
 
     *Author:* Ana Huamán
index 7e184dd..3f23a0b 100644 (file)
@@ -1,8 +1,8 @@
 /**
  * @file Drawing_1.cpp
- * @brief Simple sample code
+ * @brief Simple geometric drawing
+ * @author OpenCV team
  */
-
 #include <opencv2/core.hpp>
 #include <opencv2/imgproc.hpp>
 #include <opencv2/highgui.hpp>
@@ -83,11 +83,11 @@ int main( void ){
 
 /// Function Declaration
 
-//![myellipse]
 /**
  * @function MyEllipse
  * @brief Draw a fixed-size ellipse with different angles
  */
+//![my_ellipse]
 void MyEllipse( Mat img, double angle )
 {
   int thickness = 2;
@@ -103,13 +103,13 @@ void MyEllipse( Mat img, double angle )
        thickness,
        lineType );
 }
-//![myellipse]
+//![my_ellipse]
 
-//![myfilledcircle]
 /**
  * @function MyFilledCircle
  * @brief Draw a fixed-size filled circle
  */
+//![my_filled_circle]
 void MyFilledCircle( Mat img, Point center )
 {
   circle( img,
@@ -119,13 +119,13 @@ void MyFilledCircle( Mat img, Point center )
       FILLED,
       LINE_8 );
 }
-//![myfilledcircle]
+//![my_filled_circle]
 
-//![mypolygon]
 /**
  * @function MyPolygon
  * @brief Draw a simple concave polygon (rook)
  */
+//![my_polygon]
 void MyPolygon( Mat img )
 {
   int lineType = LINE_8;
@@ -163,17 +163,18 @@ void MyPolygon( Mat img )
         Scalar( 255, 255, 255 ),
         lineType );
 }
-//![mypolygon]
+//![my_polygon]
 
-//![myline]
 /**
  * @function MyLine
  * @brief Draw a simple line
  */
+//![my_line]
 void MyLine( Mat img, Point start, Point end )
 {
   int thickness = 2;
   int lineType = LINE_8;
+
   line( img,
     start,
     end,
@@ -181,4 +182,4 @@ void MyLine( Mat img, Point start, Point end )
     thickness,
     lineType );
 }
-//![myline]
+//![my_line]
diff --git a/samples/java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java b/samples/java/tutorial_code/core/BasicGeometricDrawing/BasicGeometricDrawing.java
new file mode 100644 (file)
index 0000000..d59d990
--- /dev/null
@@ -0,0 +1,186 @@
+import org.opencv.core.*;
+import org.opencv.core.Point;
+import org.opencv.highgui.HighGui;
+import org.opencv.imgproc.Imgproc;
+
+import java.util.*;
+import java.util.List;
+
+class GeometricDrawingRun{
+
+    private static final int W = 400;
+
+    public void run(){
+        //! [create_images]
+        /// Windows names
+        String atom_window = "Drawing 1: Atom";
+        String rook_window = "Drawing 2: Rook";
+
+        /// Create black empty images
+        Mat atom_image = Mat.zeros( W, W, CvType.CV_8UC3 );
+        Mat rook_image = Mat.zeros( W, W, CvType.CV_8UC3 );
+        //! [create_images]
+
+        //! [draw_atom]
+        /// 1. Draw a simple atom:
+        /// -----------------------
+        MyEllipse( atom_image, 90.0 );
+        MyEllipse( atom_image, 0.0 );
+        MyEllipse( atom_image, 45.0 );
+        MyEllipse( atom_image, -45.0 );
+
+        /// 1.b. Creating circles
+        MyFilledCircle( atom_image, new Point( W/2, W/2) );
+        //! [draw_atom]
+
+        //! [draw_rook]
+        /// 2. Draw a rook
+        /// ------------------
+        /// 2.a. Create a convex polygon
+        MyPolygon( rook_image );
+
+        //! [rectangle]
+        /// 2.b. Creating rectangles
+        Imgproc.rectangle( rook_image,
+                new Point( 0, 7*W/8 ),
+                new Point( W, W),
+                new Scalar( 0, 255, 255 ),
+                -1,
+                8,
+                0 );
+        //! [rectangle]
+
+        /// 2.c. Create a few lines
+        MyLine( rook_image, new Point( 0, 15*W/16 ), new Point( W, 15*W/16 ) );
+        MyLine( rook_image, new Point( W/4, 7*W/8 ), new Point( W/4, W ) );
+        MyLine( rook_image, new Point( W/2, 7*W/8 ), new Point( W/2, W ) );
+        MyLine( rook_image, new Point( 3*W/4, 7*W/8 ), new Point( 3*W/4, W ) );
+        //! [draw_rook]
+
+        /// 3. Display your stuff!
+        HighGui.imshow( atom_window, atom_image );
+        HighGui.moveWindow( atom_window, 0, 200 );
+        HighGui.imshow( rook_window, rook_image );
+        HighGui.moveWindow( rook_window, W, 200 );
+
+        HighGui.waitKey( 0 );
+        System.exit(0);
+    }
+
+    /// Function Declaration
+
+    /**
+     * @function MyEllipse
+     * @brief Draw a fixed-size ellipse with different angles
+     */
+    //! [my_ellipse]
+    private void MyEllipse( Mat img, double angle ) {
+        int thickness = 2;
+        int lineType = 8;
+        int shift = 0;
+
+        Imgproc.ellipse( img,
+                new Point( W/2, W/2 ),
+                new Size( W/4, W/16 ),
+                angle,
+                0.0,
+                360.0,
+                new Scalar( 255, 0, 0 ),
+                thickness,
+                lineType,
+                shift );
+    }
+    //! [my_ellipse]
+    /**
+     * @function MyFilledCircle
+     * @brief Draw a fixed-size filled circle
+     */
+    //! [my_filled_circle]
+    private void MyFilledCircle( Mat img, Point center ) {
+        int thickness = -1;
+        int lineType = 8;
+        int shift = 0;
+
+        Imgproc.circle( img,
+                center,
+                W/32,
+                new Scalar( 0, 0, 255 ),
+                thickness,
+                lineType,
+                shift );
+    }
+    //! [my_filled_circle]
+    /**
+     * @function MyPolygon
+     * @function Draw a simple concave polygon (rook)
+     */
+    //! [my_polygon]
+    private void MyPolygon( Mat img ) {
+        int lineType = 8;
+        int shift = 0;
+
+        /** Create some points */
+        Point[] rook_points = new Point[20];
+        rook_points[0]  = new Point(     W/4, 7*W/8   );
+        rook_points[1]  = new Point(   3*W/4, 7*W/8   );
+        rook_points[2]  = new Point(   3*W/4, 13*W/16 );
+        rook_points[3]  = new Point( 11*W/16, 13*W/16 );
+        rook_points[4]  = new Point( 19*W/32, 3*W/8   );
+        rook_points[5]  = new Point(   3*W/4, 3*W/8   );
+        rook_points[6]  = new Point(   3*W/4, W/8     );
+        rook_points[7]  = new Point( 26*W/40, W/8     );
+        rook_points[8]  = new Point( 26*W/40, W/4     );
+        rook_points[9]  = new Point( 22*W/40, W/4     );
+        rook_points[10] = new Point( 22*W/40, W/8     );
+        rook_points[11] = new Point( 18*W/40, W/8     );
+        rook_points[12] = new Point( 18*W/40, W/4     );
+        rook_points[13] = new Point( 14*W/40, W/4     );
+        rook_points[14] = new Point( 14*W/40, W/8     );
+        rook_points[15] = new Point(     W/4, W/8     );
+        rook_points[16] = new Point(     W/4, 3*W/8   );
+        rook_points[17] = new Point( 13*W/32, 3*W/8   );
+        rook_points[18] = new Point(  5*W/16, 13*W/16 );
+        rook_points[19] = new Point(     W/4, 13*W/16 );
+
+        MatOfPoint matPt = new MatOfPoint();
+        matPt.fromArray(rook_points);
+
+        List<MatOfPoint> ppt = new ArrayList<MatOfPoint>();
+        ppt.add(matPt);
+
+        Imgproc.fillPoly(img,
+                ppt,
+                new Scalar( 255, 255, 255 ),
+                lineType,
+                shift,
+                new Point(0,0) );
+    }
+    //! [my_polygon]
+    /**
+     * @function MyLine
+     * @brief Draw a simple line
+     */
+    //! [my_line]
+    private void MyLine( Mat img, Point start, Point end ) {
+        int thickness = 2;
+        int lineType = 8;
+        int shift = 0;
+
+        Imgproc.line( img,
+                start,
+                end,
+                new Scalar( 0, 0, 0 ),
+                thickness,
+                lineType,
+                shift );
+    }
+    //! [my_line]
+}
+
+public class BasicGeometricDrawing {
+    public static void main(String[] args) {
+        // Load the native library.
+        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
+        new GeometricDrawingRun().run();
+    }
+}
diff --git a/samples/python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py b/samples/python/tutorial_code/core/BasicGeometricDrawing/basic_geometric_drawing.py
new file mode 100644 (file)
index 0000000..a6f4098
--- /dev/null
@@ -0,0 +1,115 @@
+import cv2
+import numpy as np
+
+W = 400
+## [my_ellipse]
+def my_ellipse(img, angle):
+    thickness = 2
+    line_type = 8
+
+    cv2.ellipse(img,
+                (W / 2, W / 2),
+                (W / 4, W / 16),
+                angle,
+                0,
+                360,
+                (255, 0, 0),
+                thickness,
+                line_type)
+## [my_ellipse]
+## [my_filled_circle]
+def my_filled_circle(img, center):
+    thickness = -1
+    line_type = 8
+
+    cv2.circle(img,
+               center,
+               W / 32,
+               (0, 0, 255),
+               thickness,
+               line_type)
+## [my_filled_circle]
+## [my_polygon]
+def my_polygon(img):
+    line_type = 8
+
+    # Create some points
+    ppt = np.array([[W / 4, 7 * W / 8], [3 * W / 4, 7 * W / 8],
+                    [3 * W / 4, 13 * W / 16], [11 * W / 16, 13 * W / 16],
+                    [19 * W / 32, 3 * W / 8], [3 * W / 4, 3 * W / 8],
+                    [3 * W / 4, W / 8], [26 * W / 40, W / 8],
+                    [26 * W / 40, W / 4], [22 * W / 40, W / 4],
+                    [22 * W / 40, W / 8], [18 * W / 40, W / 8],
+                    [18 * W / 40, W / 4], [14 * W / 40, W / 4],
+                    [14 * W / 40, W / 8], [W / 4, W / 8],
+                    [W / 4, 3 * W / 8], [13 * W / 32, 3 * W / 8],
+                    [5 * W / 16, 13 * W / 16], [W / 4, 13 * W / 16]], np.int32)
+    ppt = ppt.reshape((-1, 1, 2))
+    cv2.fillPoly(img, [ppt], (255, 255, 255), line_type)
+    # Only drawind the lines would be:
+    # cv2.polylines(img, [ppt], True, (255, 0, 255), line_type)
+## [my_polygon]
+## [my_line]
+def my_line(img, start, end):
+    thickness = 2
+    line_type = 8
+
+    cv2.line(img,
+             start,
+             end,
+             (0, 0, 0),
+             thickness,
+             line_type)
+## [my_line]
+## [create_images]
+# Windows names
+atom_window = "Drawing 1: Atom"
+rook_window = "Drawing 2: Rook"
+
+# Create black empty images
+size = W, W, 3
+atom_image = np.zeros(size, dtype=np.uint8)
+rook_image = np.zeros(size, dtype=np.uint8)
+## [create_images]
+## [draw_atom]
+# 1. Draw a simple atom:
+# -----------------------
+
+# 1.a. Creating ellipses
+my_ellipse(atom_image, 90)
+my_ellipse(atom_image, 0)
+my_ellipse(atom_image, 45)
+my_ellipse(atom_image, -45)
+
+# 1.b. Creating circles
+my_filled_circle(atom_image, (W / 2, W / 2))
+## [draw_atom]
+## [draw_rook]
+
+# 2. Draw a rook
+# ------------------
+# 2.a. Create a convex polygon
+my_polygon(rook_image)
+## [rectangle]
+# 2.b. Creating rectangles
+cv2.rectangle(rook_image,
+              (0, 7 * W / 8),
+              (W, W),
+              (0, 255, 255),
+              -1,
+              8)
+## [rectangle]
+
+#  2.c. Create a few lines
+my_line(rook_image, (0, 15 * W / 16), (W, 15 * W / 16))
+my_line(rook_image, (W / 4, 7 * W / 8), (W / 4, W))
+my_line(rook_image, (W / 2, 7 * W / 8), (W / 2, W))
+my_line(rook_image, (3 * W / 4, 7 * W / 8), (3 * W / 4, W))
+## [draw_rook]
+cv2.imshow(atom_window, atom_image)
+cv2.moveWindow(atom_window, 0, 200)
+cv2.imshow(rook_window, rook_image)
+cv2.moveWindow(rook_window, W, 200)
+
+cv2.waitKey(0)
+cv2.destroyAllWindows()