From 35245d25091292a8573abb8138914230b64947ad Mon Sep 17 00:00:00 2001 From: Fabien Spindler Date: Wed, 3 Apr 2024 15:11:42 +0200 Subject: [PATCH] Introduce new doxygen tutorial for hsv segmentation --- ChangeLog.txt | 2 + .../segmentation/color/ballons-segmented.jpg | Bin 0 -> 43306 bytes .../color/tutorial-hsv-segmentation.dox | 128 ++++++++++++++++++ doc/tutorial/tutorial-users.dox | 10 ++ 4 files changed, 140 insertions(+) create mode 100644 doc/image/tutorial/segmentation/color/ballons-segmented.jpg create mode 100644 doc/tutorial/segmentation/color/tutorial-hsv-segmentation.dox diff --git a/ChangeLog.txt b/ChangeLog.txt index efc07b6e24..93b7a05c05 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -48,6 +48,8 @@ ViSP 3.x.x (Version in development) https://visp-doc.inria.fr/doxygen/visp-daily/tutorial-spc.html . New tutorial: Installing ViSP Python bindings https://visp-doc.inria.fr/doxygen/visp-daily/tutorial-install-python-bindings.html + . New tutorial: Color segmentation using HSV color scale + https://visp-doc.inria.fr/doxygen/visp-daily/tutorial-hsv-segmentation.html - Bug fixed . [#1251] Bug in vpDisplay::displayFrame() . [#1270] Build issue around std::clamp and optional header which are not found with cxx17 diff --git a/doc/image/tutorial/segmentation/color/ballons-segmented.jpg b/doc/image/tutorial/segmentation/color/ballons-segmented.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6b67203c3a49d39031f2919ce4def1d599b0fe03 GIT binary patch literal 43306 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 Paj>r!Y*CkB{C^Vw$pj<6 literal 0 HcmV?d00001 diff --git a/doc/tutorial/segmentation/color/tutorial-hsv-segmentation.dox b/doc/tutorial/segmentation/color/tutorial-hsv-segmentation.dox new file mode 100644 index 0000000000..bfb4660e18 --- /dev/null +++ b/doc/tutorial/segmentation/color/tutorial-hsv-segmentation.dox @@ -0,0 +1,128 @@ +/** + \page tutorial-hsv-segmentation Tutorial: Color segmentation using HSV color scale + \tableofcontents + +\section hsv_intro Introduction + +The HSV scale, which stands for Hue Saturation and Value, provides a numerical readout of your color image that +corresponds to the color names contained therein. Hue is measured in degrees from 0 to 360, while Saturation and Value +of a color are both analyzed on a scale of 0 to 100 percent. + +Hue, Saturation, and Value are the main color properties that allow us to distinguish between different colors. +In this tutorial, you will learn how to use HSV color scale to segment a specific color in an image. + +Note that all the material (source code and images) described in this tutorial is part of ViSP source code +(in `tutorial/segmentation/color` folder) and could be found in +https://github.com/lagadic/visp/tree/master/tutorial/segmentation/color. + +\section hsv_converter RGB to HSV color scale conversion + +In ViSP, color images can be read and converted to the RGB color scale. The RGB color scale is based on the color +theory that all visible colors can be obtained from the additive primary colors red, green and blue. In ViSP, +we introduce an additional Alpha channel to add color transparency. The RGB + Alpha channels are therefore +implemented in the vpRGBa class. The following snippet shows how to load a color image in ViSP: +\code +#include + +int main() +{ + vpImage I; + vpImageIo::read(I, "ballons.jpg"); +} +\endcode + +The color conversion from RGB to HSV or from RGBa to HSV color scale is performed in ViSP using one of the following +functions: +- vpImageConvert::RGBToHSV() +- vpImageConvert::RGBaToHSV() + +The following snippet shows how to convert to HSV color scale: +\code +#include +#include + +int main() +{ + vpImage I; + vpImageIo::read(I, "ballons.jpg"); + + unsigned int width = I.getWidth(); + unsigned int height = I.getHeight(); + + vpImage H(height, width); + vpImage S(height, width); + vpImage V(height, width); + + vpImageConvert::RGBaToHSV(reinterpret_cast(I.bitmap), + reinterpret_cast(H.bitmap), + reinterpret_cast(S.bitmap), + reinterpret_cast(V.bitmap), I.getSize()); +} +\endcode +In the previous example, we obtained for each pixel: +- Hue in `H` image where values are scaled from 0 to 255. here 255 stands for 360 degrees. +- Saturation in `S` image where values are scaled from 0 to 255. Here 255 stands for 100%. +- Value in `V` image where values are scaled from 0 to 255. Here 255 stands for 100%. + +\section hsv_segmentation HSV color segmentation + +It's easy to segment a given color if we select the range of hue, saturation and value we're interested in. + +In the image `ballons.jpg`, the pixel at coordinates [93][164] has an RGB value (209, 72, 0) which corresponds to +an HSV value (14, 255, 209). We can use these HSV values and an additional offset to determine the low and high +values of the HSV ranges used to create a mask corresponding to the segmented color. + +\code +#include +#include +#include + +int main() +{ + vpImage I; + vpImageIo::read(I, "ballons.jpg"); + + unsigned int width = I.getWidth(); + unsigned int height = I.getHeight(); + + vpImage H(height, width); + vpImage S(height, width); + vpImage V(height, width); + + vpImageConvert::RGBaToHSV(reinterpret_cast(I.bitmap), + reinterpret_cast(H.bitmap), + reinterpret_cast(S.bitmap), + reinterpret_cast(V.bitmap), I.getSize()); + + int h = 14, s = 255, v = 209; + int offset = 30; + int h_low = std::max(0, h - offset), h_high = std::min(h + offset, 255); + int s_low = std::max(0, s - offset), s_high = std::min(s + offset, 255); + int v_low = std::max(0, v - offset), v_high = std::min(v + offset, 255); + std::vector hsv_range({ h_low, h_high, s_low, s_high, v_low, v_high }); + + vpImage mask(height, width); + vpImageTools::inRange(reinterpret_cast(H.bitmap), + reinterpret_cast(S.bitmap), + reinterpret_cast(V.bitmap), + hsv_range, + reinterpret_cast(mask.bitmap), + mask.getSize()); +} +\endcode + +Using the mask we can create a segmented color image. The following snippet shows how to combine the mask and the +color image using vpImageTools::inMask() to create the segmented image as given in the next snippet also available in +tutorial-hsv-segmentation-basic.cpp + +\include tutorial-hsv-segmentation-basic.cpp + +The end of the previous snippet shows also how to display the following images. + +\image html ballons-segmented.jpg + +\section hsv_next Next tutorial + +You are now ready to see how to continue with \ref tutorial-grabber. + +*/ diff --git a/doc/tutorial/tutorial-users.dox b/doc/tutorial/tutorial-users.dox index 9dc2c0359f..d98444d245 100644 --- a/doc/tutorial/tutorial-users.dox +++ b/doc/tutorial/tutorial-users.dox @@ -17,6 +17,8 @@ This page references all the tutorials to use and contribute to ViSP. - \subpage tutorial_detection_dnn +- \subpage tutorial_segmentation + - \subpage tutorial_computer_vision - \subpage tutorial_vs @@ -123,6 +125,14 @@ This page introduces the user to the way to detect features or objects in images */ +/*! \page tutorial_segmentation Segmentation +This page introduces the user to the way to achieve image and object segmentation. + +- \subpage tutorial-hsv-segmentation
This tutorial shows how to use HSV color scale to segment a given color in + an image. + +*/ + /*! \page tutorial_computer_vision Computer vision This page introduces the user to the way to estimate a pose or an homography.