JeVoisBase  1.21
JeVois Smart Embedded Machine Vision Toolkit Base Modules
Share this page:
Loading...
Searching...
No Matches
DiceCounter.C
Go to the documentation of this file.
1// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2//
3// JeVois Smart Embedded Machine Vision Toolkit - Copyright (C) 2016 by Laurent Itti, the University of Southern
4// California (USC), and iLab at USC. See http://iLab.usc.edu and http://jevois.org for information about this project.
5//
6// This file is part of the JeVois Smart Embedded Machine Vision Toolkit. This program is free software; you can
7// redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software
8// Foundation, version 2. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9// without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
10// License for more details. You should have received a copy of the GNU General Public License along with this program;
11// if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12//
13// Contact information: Laurent Itti - 3641 Watt Way, HNB-07A - Los Angeles, CA 90089-2520 - USA.
14// Tel: +1 213 740 3527 - itti@pollux.usc.edu - http://iLab.usc.edu - http://jevois.org
15// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
16/*! \file */
17
18#include <jevois/Core/Module.H>
20#include <jevois/Debug/Timer.H>
21#include <opencv2/imgproc/imgproc.hpp>
22#include <opencv2/features2d.hpp>
23
24// icon by Madebyoliver in Game Collection at flaticon
25
26//! Counting dice pips
27/*! This module can help you automate counting your dice values, for example when playing games that involve throwing
28 multiple dice.
29
30 This application scenario was suggested by JeVois user mapembert at the [JeVois Tech Zone](http://jevois.org/qa)
31 in this post:
32
33 http://jevois.org/qa/index.php?qa=328
34
35 The code implemented by this module is a modified version of original code (mentioned in the above post) contributed
36 by Yohann Payet.
37
38 This module is the result of JeVois tutorial [A JeVois dice counting module in
39 C++](http://jevois.org/tutorials/ProgrammerDice.html). Also see [JeVois python tutorial: A dice counting
40 module](http://jevois.org/tutorials/ProgrammerPythonDice.html) for a Python version.
41
42 Serial messages
43 ---------------
44
45 This module sends the following serial message (remember to turn serial outputs on, using `setpar serout Hard` or
46 similar; see \ref UserCli):
47 \verbatim
48 PIPS n
49 \endverbatim
50 where \a n is the total number of pips detected. No message is sent if \a n is zero.
51
52 @author Laurent Itti
53
54 @videomapping YUYV 640 480 7.5 YUYV 640 480 7.5 SampleVendor DiceCounter
55 @email itti\@usc.edu
56 @address University of Southern California, HNB-07A, 3641 Watt Way, Los Angeles, CA 90089-2520, USA
57 @copyright Copyright (C) 2017 by Laurent Itti, iLab and the University of Southern California
58 @mainurl http://jevois.org
59 @supporturl http://jevois.org/doc
60 @otherurl http://iLab.usc.edu
61 @license GPL v3
62 @distribution Unrestricted
63 @restrictions None
64 \ingroup modules */
66{
67 public:
68 //! Constructor
69 DiceCounter(std::string const & instance) : jevois::Module(instance)
70 {
71 // Setting detector parameters
72 cv::SimpleBlobDetector::Params params;
73 params.filterByCircularity = true;
74 params.filterByArea = true;
75 params.minArea = 200.0f;
76
77 // Creating a detector object
78 itsDetector = cv::SimpleBlobDetector::create(params);
79 }
80
81 //! Virtual destructor for safe inheritance
82 virtual ~DiceCounter() { }
83
84 //! Processing function
85 virtual void process(jevois::InputFrame && inframe, jevois::OutputFrame && outframe) override
86 {
87 static jevois::Timer timer("processing");
88
89 // Wait for next available camera image:
90 jevois::RawImage const inimg = inframe.get(); unsigned int const w = inimg.width, h = inimg.height;
91
92 timer.start();
93
94 // We only support YUYV pixels in this example, any resolution:
95 inimg.require("input", inimg.width, inimg.height, V4L2_PIX_FMT_YUYV);
96
97 // Start a thread to wait for output image and copy input into output:
98 jevois::RawImage outimg;
99 std::future<void> fut = jevois::async([&]() {
100 // Wait for an image from our gadget driver into which we will put our results:
101 outimg = outframe.get();
102
103 // Enforce that the input and output formats and image sizes match:
104 outimg.require("output", w, h, inimg.fmt);
105
106 // Just copy the pixel data over:
107 jevois::rawimage::paste(inimg, outimg, 0, 0);
108 });
109
110 // Detect dice pips: First convert input to grayscale:
111 cv::Mat grayImage = jevois::rawimage::convertToCvGray(inimg);
112
113 // filter noise
114 cv::GaussianBlur(grayImage, grayImage, cv::Size(5, 5), 0, 0);
115
116 // apply automatic threshold
117 cv::threshold(grayImage, grayImage, 0.0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
118
119 // background area
120 cv::Mat kernel; // not initialized??
121 int const morphBNo2 = 2;
122 cv::dilate(grayImage, grayImage, kernel, cv::Point(-1, -1), morphBNo2);
123 cv::Mat image(grayImage.rows, grayImage.cols, CV_8U, cv::Scalar(255, 255, 255));
124 cv::Mat invBack2 = image - grayImage;
125
126 // blob detection
127 std::vector<cv::KeyPoint> keypoints;
128 itsDetector->detect(invBack2, keypoints);
129 int nrOfBlobs = keypoints.size();
130
131 // Wait until our other thread is done:
132 fut.get();
133
134 // Let camera know we are done processing the input image:
135 inframe.done();
136
137 // draw keypoints
138 for (cv::KeyPoint const & kp : keypoints)
139 jevois::rawimage::drawCircle(outimg, int(kp.pt.x + 0.5F), int(kp.pt.y + 0.5F), int(kp.size * 0.5F),
141
142 // Show number of detected pips:
143 jevois::rawimage::writeText(outimg, "JeVois dice counter: " + std::to_string(nrOfBlobs) + " pips",
144 3, 3, jevois::yuyv::White);
145
146 // Show processing fps:
147 std::string const & fpscpu = timer.stop();
148 jevois::rawimage::writeText(outimg, fpscpu, 3, h - 13, jevois::yuyv::White);
149
150 // Send the output image with our processing results to the host over USB:
151 outframe.send();
152
153 // Send serial message:
154 if (nrOfBlobs) sendSerial("PIPS " + std::to_string(nrOfBlobs));
155 }
156
157 private:
158 cv::Ptr<cv::SimpleBlobDetector> itsDetector;
159};
160
161// Allow the module to be loaded as a shared object (.so) file:
JEVOIS_REGISTER_MODULE(ArUcoBlob)
int h
Counting dice pips.
Definition DiceCounter.C:66
virtual void process(jevois::InputFrame &&inframe, jevois::OutputFrame &&outframe) override
Processing function.
Definition DiceCounter.C:85
virtual ~DiceCounter()
Virtual destructor for safe inheritance.
Definition DiceCounter.C:82
DiceCounter(std::string const &instance)
Constructor.
Definition DiceCounter.C:69
friend friend class Module
virtual void sendSerial(std::string const &str)
unsigned int fmt
unsigned int width
unsigned int height
void require(char const *info, unsigned int w, unsigned int h, unsigned int f) const
std::string const & stop(double *seconds)
void paste(RawImage const &src, RawImage &dest, int dx, int dy)
void writeText(RawImage &img, std::string const &txt, int x, int y, unsigned int col, Font font=Font6x10)
cv::Mat convertToCvGray(RawImage const &src)
void drawCircle(RawImage &img, int x, int y, unsigned int rad, unsigned int thick, unsigned int col)
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async(Function &&f, Args &&... args)
unsigned short constexpr White
unsigned short constexpr LightGreen