JeVoisBase  1.20
JeVois Smart Embedded Machine Vision Toolkit Base Modules
Share this page:
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),
140  2, jevois::yuyv::LightGreen);
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::OutputFrame
jevois::async
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async(Function &&f, Args &&... args)
Timer.H
Module.H
JEVOIS_REGISTER_MODULE
JEVOIS_REGISTER_MODULE(DiceCounter)
jevois::RawImage
jevois::rawimage::drawCircle
void drawCircle(RawImage &img, int x, int y, unsigned int rad, unsigned int thick, unsigned int col)
jevois::Timer::start
void start()
jevois::rawimage::convertToCvGray
cv::Mat convertToCvGray(RawImage const &src)
jevois::RawImage::require
void require(char const *info, unsigned int w, unsigned int h, unsigned int f) const
demo.image
image
Definition: demo.py:84
jevois::RawImage::width
unsigned int width
jevois::rawimage::writeText
void writeText(RawImage &img, std::string const &txt, int x, int y, unsigned int col, Font font=Font6x10)
jevois
jevois::Timer::stop
const std::string & stop(double *seconds)
jevois::Module
RawImageOps.H
jevois::RawImage::height
unsigned int height
to_string
std::string to_string(T const &val)
jevois::InputFrame
DiceCounter::DiceCounter
DiceCounter(std::string const &instance)
Constructor.
Definition: DiceCounter.C:69
jevois::rawimage::paste
void paste(RawImage const &src, RawImage &dest, int dx, int dy)
jevois::RawImage::fmt
unsigned int fmt
h
int h
jevois::Module::sendSerial
virtual void sendSerial(std::string const &str)
DiceCounter
Counting dice pips.
Definition: DiceCounter.C:65
DiceCounter::~DiceCounter
virtual ~DiceCounter()
Virtual destructor for safe inheritance.
Definition: DiceCounter.C:82
demo.w
w
Definition: demo.py:85
DiceCounter::process
virtual void process(jevois::InputFrame &&inframe, jevois::OutputFrame &&outframe) override
Processing function.
Definition: DiceCounter.C:85
jevois::Timer
jevois::Component::Module
friend friend class Module