42#include <visp3/core/vpImageTools.h>
43#include <visp3/core/vpIoTools.h>
44#include <visp3/imgproc/vpImgproc.h>
45#include <visp3/io/vpImageIo.h>
46#include <visp3/io/vpParseArgv.h>
49#define GETOPTARGS "cdi:o:h"
51#ifdef ENABLE_VISP_NAMESPACE
55void usage(
const char *name,
const char *badparam,
const std::string &ipath,
const std::string &opath,
const std::string &user);
56bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &opath, std::string user);
68void usage(
const char *name,
const char *badparam,
const std::string &ipath,
const std::string &opath,
const std::string &user)
71Test connected components.\n\
74 %s [-i <input image path>] [-o <output image path>]\n\
81 -i <input image path> %s\n\
82 Set image input path.\n\
83 From this path read \"Klimt/Klimt.pgm\"\n\
85 Setting the VISP_INPUT_IMAGE_PATH environment\n\
86 variable produces the same behaviour than using\n\
89 -o <output image path> %s\n\
90 Set image output path.\n\
91 From this directory, creates the \"%s\"\n\
92 subdirectory depending on the username, where \n\
93 output result images are written.\n\
97 ipath.c_str(), opath.c_str(), user.c_str());
100 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
114bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &opath, std::string user)
128 usage(argv[0],
nullptr, ipath, opath, user);
136 usage(argv[0], optarg_, ipath, opath, user);
141 if ((c == 1) || (c == -1)) {
143 usage(argv[0],
nullptr, ipath, opath, user);
144 std::cerr <<
"ERROR: " << std::endl;
145 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
157 std::map<int, std::vector<vpImagePoint> > map_label1, map_label2;
158 for (
unsigned int i = 0;
i < label1.
getHeight();
i++) {
159 for (
unsigned int j = 0;
j < label1.
getWidth();
j++) {
160 if ((label1[i][j] > 0 && label2[i][j] == 0) || (label1[i][j] == 0 && label2[i][j] > 0)) {
161 std::cerr <<
"label1[i][j] > 0 && label2[i][j] == 0 || label1[i][j] "
162 "== 0 && label2[i][j] > 0"
175 if (map_label1.size() != map_label2.size()) {
176 std::cerr <<
"map_label1.size() != map_label2.size()" << std::endl;
180 for (std::map<
int, std::vector<vpImagePoint> >::const_iterator it1 = map_label1.begin(); it1 != map_label1.end();
183 unsigned int i =
static_cast<unsigned int>(it1->second.front().get_i()),
j =
static_cast<unsigned int>(it1->second.front().get_j());
184 int lab2 = label2[
i][
j];
186 std::vector<vpImagePoint>::const_iterator it_pt1 = it1->second.begin();
187 for (; it_pt1 != it1->second.end(); ++it_pt1) {
188 i =
static_cast<unsigned int>(it_pt1->get_i());
189 j =
static_cast<unsigned int>(it_pt1->get_j());
190 if (label2[i][j] != lab2) {
191 std::cerr <<
"label2[i][j] != lab2" << std::endl;
200int main(
int argc,
const char **argv)
203 std::string env_ipath;
204 std::string opt_ipath;
205 std::string opt_opath;
209 std::string username;
216 if (!env_ipath.empty())
221 opt_opath =
"C:/temp";
230 if (getOptions(argc, argv, opt_ipath, opt_opath, username) ==
false) {
235 if (!opt_ipath.empty())
237 if (!opt_opath.empty())
250 usage(argv[0],
nullptr, ipath, opt_opath, username);
251 std::cerr << std::endl <<
"ERROR:" << std::endl;
252 std::cerr <<
" Cannot create " << opath << std::endl;
253 std::cerr <<
" Check your -o " << opt_opath <<
" option " << std::endl;
260 if (!opt_ipath.empty() && !env_ipath.empty()) {
261 if (ipath != env_ipath) {
262 std::cout << std::endl <<
"WARNING: " << std::endl;
263 std::cout <<
" Since -i <visp image path=" << ipath <<
"> "
264 <<
" is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
265 <<
" we skip the environment variable." << std::endl;
270 if (opt_ipath.empty() && env_ipath.empty()) {
271 usage(argv[0],
nullptr, ipath, opt_opath, username);
272 std::cerr << std::endl <<
"ERROR:" << std::endl;
273 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
274 <<
" environment variable to specify the location of the " << std::endl
275 <<
" image path where test images are located." << std::endl
287 std::cout <<
"Read image: " <<
filename << std::endl;
291 std::cout <<
"Image: " << I.getWidth() <<
"x" << I.getHeight() << std::endl;
294 int nbComponents = 0;
298 std::cout <<
"\n4-connexity connected components:" << std::endl;
299 std::cout <<
"Time: " <<
t <<
" ms" << std::endl;
300 std::cout <<
"nbComponents=" << nbComponents << std::endl;
306 std::cout <<
"\n8-connexity connected components:" << std::endl;
307 std::cout <<
"Time: " <<
t <<
" ms" << std::endl;
308 std::cout <<
"nbComponents=" << nbComponents << std::endl;
312 for (
unsigned int i = 0;
i < labels_connex4.
getHeight();
i++) {
313 for (
unsigned int j = 0;
j < labels_connex4.
getWidth();
j++) {
314 if (labels_connex4[i][j] != 0) {
326 for (
unsigned int i = 0;
i < labels_connex8.
getHeight();
i++) {
327 for (
unsigned int j = 0;
j < labels_connex8.
getWidth();
j++) {
328 if (labels_connex8[i][j] != 0) {
339#if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(HAVE_OPENCV_IMGPROC)
345 cv::connectedComponents(matImg, matLabels_4, 4);
348 std::set<int> set_labels_connex4_opencv;
349 vpImage<int> labels_connex4_opencv(
static_cast<unsigned int>(matLabels_4.rows),
static_cast<unsigned int>(matLabels_4.cols));
350 for (
int i = 0;
i < matLabels_4.rows;
i++) {
351 for (
int j = 0;
j < matLabels_4.cols;
j++) {
352 labels_connex4_opencv[
i][
j] = matLabels_4.at<
int>(
i,
j);
354 if (matLabels_4.at<
int>(i, j))
355 set_labels_connex4_opencv.insert(matLabels_4.at<
int>(i, j));
359 std::cout <<
"\n4-connexity connected components (OpenCV):" << std::endl;
360 std::cout <<
"Time: " << t_opencv <<
" ms" << std::endl;
361 std::cout <<
"nb components: " << set_labels_connex4_opencv.size() << std::endl;
362 bool check_label = checkLabels(labels_connex4_opencv, labels_connex4);
363 std::cout <<
"checkLabels(labels_connex4_opencv, labels_connex4): " << check_label << std::endl;
372 cv::connectedComponents(matImg, matLabels_8, 8);
375 std::set<int> set_labels_connex8_opencv;
376 vpImage<int> labels_connex8_opencv(
static_cast<unsigned int>(matLabels_8.rows),
static_cast<unsigned int>(matLabels_8.cols));
377 for (
int i = 0;
i < matLabels_8.rows;
i++) {
378 for (
int j = 0;
j < matLabels_8.cols;
j++) {
379 labels_connex8_opencv[
i][
j] = matLabels_8.at<
int>(
i,
j);
381 if (matLabels_8.at<
int>(i, j))
382 set_labels_connex8_opencv.insert(matLabels_8.at<
int>(i, j));
386 std::cout <<
"\n8-connexity connected components (OpenCV):" << std::endl;
387 std::cout <<
"nb components: " << set_labels_connex8_opencv.size() << std::endl;
388 std::cout <<
"Time: " << t_opencv <<
" ms" << std::endl;
389 check_label = checkLabels(labels_connex8_opencv, labels_connex8);
390 std::cout <<
"checkLabels(labels_connex8_opencv, labels_connex8): " << check_label << std::endl;
402 std::cerr <<
"Catch an exception: " <<
e.what() << std::endl;
static vpColor getColor(const unsigned int &i)
error that can be emitted by ViSP classes.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
unsigned int getWidth() const
unsigned int getHeight() const
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
VISP_EXPORT void connectedComponents(const VISP_NAMESPACE_ADDRESSING vpImage< unsigned char > &I, VISP_NAMESPACE_ADDRESSING vpImage< int > &labels, int &nbComponents, const VISP_NAMESPACE_ADDRESSING vpImageMorphology::vpConnexityType &connexity=VISP_NAMESPACE_ADDRESSING vpImageMorphology::CONNEXITY_4)
VISP_EXPORT double measureTimeMs()