Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
vpImageMorphology.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Image morphology.
32  *
33  * Authors:
34  * Souriya Trinh
35  *
36  *****************************************************************************/
37 
38 #include <visp3/core/vpImageMorphology.h>
39 
40 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2)
41 # include <emmintrin.h>
42 # define VISP_HAVE_SSE2 1
43 #endif
44 
45 
69  if(I.getSize() == 0) {
70  std::cerr << "Input image is empty!" << std::endl;
71  return;
72  }
73 
74  const unsigned char null_value = 255;
75 
77  // Copy I to J and add border
78  for (unsigned int i = 0; i < J.getHeight(); i++) {
79  if (i == 0 || i == J.getHeight() - 1) {
80  for (unsigned int j = 0; j < J.getWidth(); j++) {
81  J[i][j] = null_value;
82  }
83  } else {
84  J[i][0] = null_value;
85  memcpy(J[i]+1, I[i-1], sizeof(unsigned char)*I.getWidth());
86  J[i][J.getWidth() - 1] = null_value;
87  }
88  }
89 
90  if (connexity == CONNEXITY_4) {
91  unsigned int offset[5] = {1, J.getWidth(), J.getWidth()+1, J.getWidth()+2, J.getWidth()*2 + 1};
92 
93  for (unsigned int i = 0; i < I.getHeight(); i++) {
94  unsigned int j = 0;
95  unsigned char *ptr_curr_J = J.bitmap + i*J.getWidth();
96  unsigned char *ptr_curr_I = I.bitmap + i*I.getWidth();
97 
98 #if VISP_HAVE_SSE2
99  if (I.getWidth() >= 16) {
100 
101  for (; j <= I.getWidth() - 16; j+=16) {
102  __m128i m = _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[0]) );
103  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[1])) );
104  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[2])) );
105  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[3])) );
106  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[4])) );
107 
108  _mm_storeu_si128( (__m128i *) (ptr_curr_I + j), m );
109  }
110  }
111 #endif
112 
113  for (; j < I.getWidth(); j++) {
114  unsigned char min_value = null_value;
115  for (int k = 0; k < 5; k++) {
116  min_value = std::min(min_value, *(ptr_curr_J + j + offset[k]));
117  }
118 
119  *(ptr_curr_I + j) = min_value;
120  }
121  }
122  } else {
123  //CONNEXITY_8
124  unsigned int offset[9] = {0, 1, 2, J.getWidth(), J.getWidth()+1, J.getWidth()+2,
125  J.getWidth()*2, J.getWidth()*2 + 1, J.getWidth()*2 + 2};
126 
127  for (unsigned int i = 0; i < I.getHeight(); i++) {
128  unsigned int j = 0;
129  unsigned char *ptr_curr_J = J.bitmap + i*J.getWidth();
130  unsigned char *ptr_curr_I = I.bitmap + i*I.getWidth();
131 
132 #if VISP_HAVE_SSE2
133  if (I.getWidth() >= 16) {
134 
135  for (; j <= I.getWidth() - 16; j+=16) {
136  __m128i m = _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[0]) );
137  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[1])) );
138  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[2])) );
139  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[3])) );
140  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[4])) );
141  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[5])) );
142  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[6])) );
143  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[7])) );
144  m = _mm_min_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[8])) );
145 
146  _mm_storeu_si128( (__m128i *) (ptr_curr_I + j), m );
147  }
148  }
149 #endif
150 
151  for (; j < I.getWidth(); j++) {
152  unsigned char min_value = null_value;
153  for (int k = 0; k < 9; k++) {
154  min_value = std::min(min_value, *(ptr_curr_J + j + offset[k]));
155  }
156 
157  *(ptr_curr_I + j) = min_value;
158  }
159  }
160  }
161 }
162 
186  if(I.getSize() == 0) {
187  std::cerr << "Input image is empty!" << std::endl;
188  return;
189  }
190 
191  const unsigned char null_value = 0;
192 
193  vpImage<unsigned char> J(I.getHeight()+2, I.getWidth()+2);
194  // Copy I to J and add border
195  for (unsigned int i = 0; i < J.getHeight(); i++) {
196  if (i == 0 || i == J.getHeight() - 1) {
197  for (unsigned int j = 0; j < J.getWidth(); j++) {
198  J[i][j] = null_value;
199  }
200  } else {
201  J[i][0] = null_value;
202  memcpy(J[i]+1, I[i-1], sizeof(unsigned char)*I.getWidth());
203  J[i][J.getWidth() - 1] = null_value;
204  }
205  }
206 
207  if (connexity == CONNEXITY_4) {
208  unsigned int offset[5] = {1, J.getWidth(), J.getWidth()+1, J.getWidth()+2, J.getWidth()*2 + 1};
209 
210  for (unsigned int i = 0; i < I.getHeight(); i++) {
211  unsigned int j = 0;
212  unsigned char *ptr_curr_J = J.bitmap + i*J.getWidth();
213  unsigned char *ptr_curr_I = I.bitmap + i*I.getWidth();
214 
215 #if VISP_HAVE_SSE2
216  if (I.getWidth() >= 16) {
217 
218  for (; j <= I.getWidth() - 16; j+=16) {
219  __m128i m = _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[0]) );
220  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[1])) );
221  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[2])) );
222  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[3])) );
223  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[4])) );
224 
225  _mm_storeu_si128( (__m128i *) (ptr_curr_I + j), m );
226  }
227  }
228 #endif
229 
230  for (; j < I.getWidth(); j++) {
231  unsigned char max_value = null_value;
232  for (int k = 0; k < 5; k++) {
233  max_value = std::max(max_value, *(ptr_curr_J + j + offset[k]));
234  }
235 
236  *(ptr_curr_I + j) = max_value;
237  }
238  }
239  } else {
240  //CONNEXITY_8
241  unsigned int offset[9] = {0, 1, 2, J.getWidth(), J.getWidth()+1, J.getWidth()+2,
242  J.getWidth()*2, J.getWidth()*2 + 1, J.getWidth()*2 + 2};
243 
244  for (unsigned int i = 0; i < I.getHeight(); i++) {
245  unsigned int j = 0;
246  unsigned char *ptr_curr_J = J.bitmap + i*J.getWidth();
247  unsigned char *ptr_curr_I = I.bitmap + i*I.getWidth();
248 
249 #if VISP_HAVE_SSE2
250  if (I.getWidth() >= 16) {
251 
252  for (; j <= I.getWidth() - 16; j+=16) {
253  __m128i m = _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[0]) );
254  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[1])) );
255  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[2])) );
256  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[3])) );
257  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[4])) );
258  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[5])) );
259  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[6])) );
260  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[7])) );
261  m = _mm_max_epu8(m, _mm_loadu_si128( (const __m128i *) (ptr_curr_J + j + offset[8])) );
262 
263  _mm_storeu_si128( (__m128i *) (ptr_curr_I + j), m );
264  }
265  }
266 #endif
267 
268  for (; j < I.getWidth(); j++) {
269  unsigned char max_value = null_value;
270  for (int k = 0; k < 9; k++) {
271  max_value = std::max(max_value, *(ptr_curr_J + j + offset[k]));
272  }
273 
274  *(ptr_curr_I + j) = max_value;
275  }
276  }
277  }
278 }
static void dilatation(vpImage< Type > &I, Type value, Type value_out, vpConnexityType connexity=CONNEXITY_4)
unsigned int getWidth() const
Definition: vpImage.h:226
Type * bitmap
points toward the bitmap
Definition: vpImage.h:134
static void erosion(vpImage< Type > &I, Type value, Type value_out, vpConnexityType connexity=CONNEXITY_4)
unsigned int getSize() const
Definition: vpImage.h:212
unsigned int getHeight() const
Definition: vpImage.h:175