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 virtual T operator()(
const T &,
const T &) = 0;
149 template <
typename T>
150 class vpPixelOperationMax :
public vpPixelOperation<T>
153 vpPixelOperationMax() { }
155 virtual T operator()(
const T &a,
const T &b) VP_OVERRIDE
157 return std::max<T>(a, b);
161 template <
typename T>
162 class vpPixelOperationMin :
public vpPixelOperation<T>
165 vpPixelOperationMin() { }
167 T operator()(
const T &a,
const T &b) VP_OVERRIDE
169 return std::min<T>(a, b);
184 template <
typename T>
185 static void imageOperation(
vpImage<T> &I,
const T &null_value, vpPixelOperation<T> *operation,
const vpConnexityType &connexity = CONNEXITY_4);
196 template <
typename T>
197 static void imageOperation(
vpImage<T> &I, vpPixelOperation<T> *operation,
const int &size = 3);
218 template <
class Type>
222 std::cerr <<
"Input image is empty!" << std::endl;
229 unsigned int j_width = J.
getWidth();
230 for (
unsigned int i = 0; i < j_height; ++i) {
231 if ((i == 0) || (i == (j_height - 1))) {
232 for (
unsigned int j = 0; j < j_width; ++j) {
238 memcpy(J[i] + 1, I[i - 1],
sizeof(
unsigned char) * I.
getWidth());
245 unsigned int i_width = I.
getWidth();
246 for (
unsigned int i = 0; i < i_height; ++i) {
247 for (
unsigned int j = 0; j < i_width; ++j) {
248 if (J[i + 1][j + 1] == value) {
250 if ((J[i][j + 1] == value_out) ||
251 (J[i + 2][j + 1] == value_out) ||
252 (J[i + 1][j] == value_out) ||
253 (J[i + 1][j + 2] == value_out)) {
262 unsigned int i_width = I.
getWidth();
263 for (
unsigned int i = 0; i < i_height; ++i) {
264 for (
unsigned int j = 0; j < i_width; ++j) {
265 if (J[i + 1][j + 1] == value) {
267 bool cond4firstneighbors = (J[i][j] == value_out) || (J[i][j + 1] == value_out) ||
268 (J[i][j + 2] == value_out) || (J[i + 1][j] == value_out);
269 bool cond4secondneighbors = (J[i + 1][j + 2] == value_out) || (J[i + 2][j] == value_out) ||
270 (J[i + 2][j + 1] == value_out) || (J[i + 2][j + 2] == value_out);
271 if (cond4firstneighbors || cond4secondneighbors) {
297 template <
class Type>
301 std::cerr <<
"Input image is empty!" << std::endl;
308 unsigned int j_width = J.
getWidth();
309 for (
unsigned int i = 0; i < j_height; ++i) {
310 if ((i == 0) || (i == (j_height - 1))) {
311 for (
unsigned int j = 0; j < j_width; ++j) {
317 memcpy(J[i] + 1, I[i - 1],
sizeof(
unsigned char) * I.
getWidth());
324 unsigned int i_width = I.
getWidth();
325 for (
unsigned int i = 0; i < i_height; ++i) {
326 for (
unsigned int j = 0; j < i_width; ++j) {
327 if (J[i + 1][j + 1] == value_out) {
329 if ((J[i][j + 1] == value) ||
330 (J[i + 2][j + 1] == value) ||
331 (J[i + 1][j] == value) ||
332 (J[i + 1][j + 2] == value)) {
341 unsigned int i_width = I.
getWidth();
342 for (
unsigned int i = 0; i < i_height; ++i) {
343 for (
unsigned int j = 0; j < i_width; ++j) {
344 if (J[i + 1][j + 1] == value_out) {
346 bool cond4firstneighbors = (J[i][j] == value) || (J[i][j + 1] == value) || (J[i][j + 2] == value) || (J[i + 1][j] == value);
347 bool cond4secondneighbors = (J[i + 1][j + 2] == value) || (J[i + 2][j] == value) || (J[i + 2][j + 1] == value) ||
348 (J[i + 2][j + 2] == value);
349 if (cond4firstneighbors || cond4secondneighbors) {
359 void vpImageMorphology::imageOperation(
vpImage<T> &I,
const T &null_value, vpPixelOperation<T> *operation,
const vpConnexityType &connexity)
363 const int width_dilat = width_in + 2;
364 const int height_dilat = height_in + 2;
365 vpImage<T> J(height_dilat, width_dilat, null_value);
371 const int nbOffset = 5;
372 int offset_x[nbOffset] = { 0, -1, 0, 1, 0 };
373 int offset_y[nbOffset] = { -1, 0, 0, 0, 1 };
375 for (
int i = 0; i < height_in; ++i) {
376 for (
int j = 0; j < width_in; ++j) {
377 T value = null_value;
378 for (
int k = 0; k < nbOffset; ++k) {
379 value = (*operation)(value, J[i + 1 + offset_y[k]][j + 1 + offset_x[k]]);
387 const int nbOffset = 9;
388 int offset_x[nbOffset] = { -1, 0, 1,-1, 0, 1,-1, 0, 1 };
389 int offset_y[nbOffset] = { -1,-1,-1, 0, 0, 0, 1, 1, 1 };
391 for (
int i = 0; i < height_in; ++i) {
392 for (
int j = 0; j < width_in; ++j) {
393 T value = null_value;
394 for (
int k = 0; k < nbOffset; ++k) {
395 value = (*operation)(value, J[i + 1 + offset_y[k]][j + 1 + offset_x[k]]);
427 template <
typename T>
430 vpPixelOperationMin<T> operation;
431 vpImageMorphology::imageOperation(I, std::numeric_limits<T>::max(), &operation, connexity);
457 template <
typename T>
460 vpPixelOperationMax<T> operation;
461 vpImageMorphology::imageOperation(I, std::numeric_limits<T>::min(), &operation, connexity);
465 void vpImageMorphology::imageOperation(
vpImage<T> &I, vpPixelOperation<T> *operation,
const int &size)
467 if ((size % 2) != 1) {
473 int halfKernelSize = size / 2;
476 for (
int r = 0; r < height_in; ++r) {
478 int r_iterator_start = -halfKernelSize, r_iterator_stop = halfKernelSize + 1;
479 if ((r - halfKernelSize) < 0) {
480 r_iterator_start = -r;
482 else if ((r + halfKernelSize) >= height_in) {
483 r_iterator_stop = height_in - r;
485 for (
int c = 0; c < width_in; ++c) {
488 int c_iterator_start = -halfKernelSize, c_iterator_stop = halfKernelSize + 1;
489 if ((c - halfKernelSize) < 0) {
490 c_iterator_start = -c;
492 else if ((c + halfKernelSize) >= width_in) {
493 c_iterator_stop = width_in - c;
495 for (
int r_iterator = r_iterator_start; r_iterator < r_iterator_stop; ++r_iterator) {
496 for (
int c_iterator = c_iterator_start; c_iterator < c_iterator_stop; ++c_iterator) {
497 value = (*operation)(value, J[r + r_iterator][c + c_iterator]);
531 template <
typename T>
534 vpPixelOperationMin<T> operation;
535 vpImageMorphology::imageOperation(I, &operation, size);
566 vpPixelOperationMax<T> operation;
567 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