40 #ifndef VP_IMAGE_MORPHOLOGY_H
41 #define VP_IMAGE_MORPHOLOGY_H
43 #include <visp3/core/vpConfig.h>
44 #include <visp3/core/vpImage.h>
45 #include <visp3/core/vpImageException.h>
46 #include <visp3/core/vpMatrix.h>
82 static void erosion(
vpImage<Type> &I, Type value, Type value_out, vpConnexityType connexity = CONNEXITY_4);
85 static void dilatation(
vpImage<Type> &I, Type value, Type value_out, vpConnexityType connexity = CONNEXITY_4);
88 static void erosion(
vpImage<T> &I,
const vpConnexityType &connexity = CONNEXITY_4);
91 static void dilatation(
vpImage<T> &I,
const vpConnexityType &connexity = CONNEXITY_4);
94 static void erosion(
vpImage<T> &I,
const int &size);
97 static void dilatation(
vpImage<T> &I,
const int &size);
99 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
115 VP_DEPRECATED
static void erosion(
vpImage<unsigned char> &I,
const vpConnexityType &connexity = CONNEXITY_4)
117 vpImageMorphology::erosion<unsigned char>(I, connexity);
132 VP_DEPRECATED
static void dilatation(
vpImage<unsigned char> &I,
const vpConnexityType &connexity = CONNEXITY_4)
134 vpImageMorphology::dilatation<unsigned char>(I, connexity);
140 template <
typename T>
141 class vpPixelOperation
144 vpPixelOperation() { }
146 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
147 virtual ~vpPixelOperation() =
default;
150 virtual T operator()(
const T &,
const T &) = 0;
153 template <
typename T>
154 class vpPixelOperationMax :
public vpPixelOperation<T>
157 vpPixelOperationMax() { }
159 virtual T operator()(
const T &a,
const T &b) VP_OVERRIDE
161 return std::max<T>(a, b);
165 template <
typename T>
166 class vpPixelOperationMin :
public vpPixelOperation<T>
169 vpPixelOperationMin() { }
171 T operator()(
const T &a,
const T &b) VP_OVERRIDE
173 return std::min<T>(a, b);
188 template <
typename T>
189 static void imageOperation(
vpImage<T> &I,
const T &null_value, vpPixelOperation<T> *operation,
const vpConnexityType &connexity = CONNEXITY_4);
200 template <
typename T>
201 static void imageOperation(
vpImage<T> &I, vpPixelOperation<T> *operation,
const int &size = 3);
222 template <
class Type>
226 std::cerr <<
"Input image is empty!" << std::endl;
233 unsigned int j_width = J.
getWidth();
234 for (
unsigned int i = 0; i < j_height; ++i) {
235 if ((i == 0) || (i == (j_height - 1))) {
236 for (
unsigned int j = 0; j < j_width; ++j) {
242 memcpy(J[i] + 1, I[i - 1],
sizeof(
unsigned char) * I.
getWidth());
249 unsigned int i_width = I.
getWidth();
250 for (
unsigned int i = 0; i < i_height; ++i) {
251 for (
unsigned int j = 0; j < i_width; ++j) {
252 if (J[i + 1][j + 1] == value) {
254 if ((J[i][j + 1] == value_out) ||
255 (J[i + 2][j + 1] == value_out) ||
256 (J[i + 1][j] == value_out) ||
257 (J[i + 1][j + 2] == value_out)) {
266 unsigned int i_width = I.
getWidth();
267 for (
unsigned int i = 0; i < i_height; ++i) {
268 for (
unsigned int j = 0; j < i_width; ++j) {
269 if (J[i + 1][j + 1] == value) {
271 bool cond4firstneighbors = (J[i][j] == value_out) || (J[i][j + 1] == value_out) ||
272 (J[i][j + 2] == value_out) || (J[i + 1][j] == value_out);
273 bool cond4secondneighbors = (J[i + 1][j + 2] == value_out) || (J[i + 2][j] == value_out) ||
274 (J[i + 2][j + 1] == value_out) || (J[i + 2][j + 2] == value_out);
275 if (cond4firstneighbors || cond4secondneighbors) {
301 template <
class Type>
305 std::cerr <<
"Input image is empty!" << std::endl;
312 unsigned int j_width = J.
getWidth();
313 for (
unsigned int i = 0; i < j_height; ++i) {
314 if ((i == 0) || (i == (j_height - 1))) {
315 for (
unsigned int j = 0; j < j_width; ++j) {
321 memcpy(J[i] + 1, I[i - 1],
sizeof(
unsigned char) * I.
getWidth());
328 unsigned int i_width = I.
getWidth();
329 for (
unsigned int i = 0; i < i_height; ++i) {
330 for (
unsigned int j = 0; j < i_width; ++j) {
331 if (J[i + 1][j + 1] == value_out) {
333 if ((J[i][j + 1] == value) ||
334 (J[i + 2][j + 1] == value) ||
335 (J[i + 1][j] == value) ||
336 (J[i + 1][j + 2] == value)) {
345 unsigned int i_width = I.
getWidth();
346 for (
unsigned int i = 0; i < i_height; ++i) {
347 for (
unsigned int j = 0; j < i_width; ++j) {
348 if (J[i + 1][j + 1] == value_out) {
350 bool cond4firstneighbors = (J[i][j] == value) || (J[i][j + 1] == value) || (J[i][j + 2] == value) || (J[i + 1][j] == value);
351 bool cond4secondneighbors = (J[i + 1][j + 2] == value) || (J[i + 2][j] == value) || (J[i + 2][j + 1] == value) ||
352 (J[i + 2][j + 2] == value);
353 if (cond4firstneighbors || cond4secondneighbors) {
363 void vpImageMorphology::imageOperation(
vpImage<T> &I,
const T &null_value, vpPixelOperation<T> *operation,
const vpConnexityType &connexity)
367 const int width_dilat = width_in + 2;
368 const int height_dilat = height_in + 2;
369 vpImage<T> J(height_dilat, width_dilat, null_value);
375 const int nbOffset = 5;
376 int offset_x[nbOffset] = { 0, -1, 0, 1, 0 };
377 int offset_y[nbOffset] = { -1, 0, 0, 0, 1 };
379 for (
int i = 0; i < height_in; ++i) {
380 for (
int j = 0; j < width_in; ++j) {
381 T value = null_value;
382 for (
int k = 0; k < nbOffset; ++k) {
383 value = (*operation)(value, J[i + 1 + offset_y[k]][j + 1 + offset_x[k]]);
391 const int nbOffset = 9;
392 int offset_x[nbOffset] = { -1, 0, 1,-1, 0, 1,-1, 0, 1 };
393 int offset_y[nbOffset] = { -1,-1,-1, 0, 0, 0, 1, 1, 1 };
395 for (
int i = 0; i < height_in; ++i) {
396 for (
int j = 0; j < width_in; ++j) {
397 T value = null_value;
398 for (
int k = 0; k < nbOffset; ++k) {
399 value = (*operation)(value, J[i + 1 + offset_y[k]][j + 1 + offset_x[k]]);
431 template <
typename T>
434 vpPixelOperationMin<T> operation;
435 vpImageMorphology::imageOperation(I, std::numeric_limits<T>::max(), &operation, connexity);
461 template <
typename T>
464 vpPixelOperationMax<T> operation;
465 vpImageMorphology::imageOperation(I, std::numeric_limits<T>::min(), &operation, connexity);
469 void vpImageMorphology::imageOperation(
vpImage<T> &I, vpPixelOperation<T> *operation,
const int &size)
471 if ((size % 2) != 1) {
477 int halfKernelSize = size / 2;
480 for (
int r = 0; r < height_in; ++r) {
482 int r_iterator_start = -halfKernelSize, r_iterator_stop = halfKernelSize + 1;
483 if ((r - halfKernelSize) < 0) {
484 r_iterator_start = -r;
486 else if ((r + halfKernelSize) >= height_in) {
487 r_iterator_stop = height_in - r;
489 for (
int c = 0; c < width_in; ++c) {
492 int c_iterator_start = -halfKernelSize, c_iterator_stop = halfKernelSize + 1;
493 if ((c - halfKernelSize) < 0) {
494 c_iterator_start = -c;
496 else if ((c + halfKernelSize) >= width_in) {
497 c_iterator_stop = width_in - c;
499 for (
int r_iterator = r_iterator_start; r_iterator < r_iterator_stop; ++r_iterator) {
500 for (
int c_iterator = c_iterator_start; c_iterator < c_iterator_stop; ++c_iterator) {
501 value = (*operation)(value, J[r + r_iterator][c + c_iterator]);
535 template <
typename T>
538 vpPixelOperationMin<T> operation;
539 vpImageMorphology::imageOperation(I, &operation, size);
570 vpPixelOperationMax<T> operation;
571 vpImageMorphology::imageOperation(I, &operation, size);
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
Various mathematical morphology tools, erosion, dilatation...
static void dilatation(vpImage< Type > &I, Type value, Type value_out, vpConnexityType connexity=CONNEXITY_4)
static void erosion(vpImage< Type > &I, Type value, Type value_out, vpConnexityType connexity=CONNEXITY_4)
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 getSize() const
unsigned int getHeight() const