39 #include <visp3/core/vpCPUFeatures.h> 40 #include <visp3/core/vpImageMorphology.h> 42 #if defined __SSE2__ || defined _M_X64 || (defined _M_IX86_FP && _M_IX86_FP >= 2) 43 #include <emmintrin.h> 44 #define VISP_HAVE_SSE2 1 73 std::cerr <<
"Input image is empty!" << std::endl;
77 const unsigned char null_value = 255;
81 for (
unsigned int i = 0; i < J.getHeight(); i++) {
82 if (i == 0 || i == J.getHeight() - 1) {
83 for (
unsigned int j = 0; j < J.getWidth(); j++) {
88 memcpy(J[i] + 1, I[i - 1],
sizeof(
unsigned char) * I.
getWidth());
89 J[i][J.getWidth() - 1] = null_value;
94 unsigned int offset[5] = {1, J.
getWidth(), J.getWidth() + 1, J.getWidth() + 2, J.getWidth() * 2 + 1};
99 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
101 unsigned char *ptr_curr_J = J.bitmap + i * J.getWidth();
105 if (checkSSE2 && I.
getWidth() >= 16) {
106 for (; j <= I.
getWidth() - 16; j += 16) {
107 __m128i m = _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[0]));
108 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[1])));
109 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[2])));
110 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[3])));
111 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[4])));
113 _mm_storeu_si128((__m128i *)(ptr_curr_I + j), m);
119 unsigned char min_value = null_value;
120 for (
int k = 0; k < 5; k++) {
121 min_value = (std::min)(min_value, *(ptr_curr_J + j + offset[k]));
124 *(ptr_curr_I + j) = min_value;
129 unsigned int offset[9] = {0,
136 J.getWidth() * 2 + 1,
137 J.getWidth() * 2 + 2};
142 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
144 unsigned char *ptr_curr_J = J.bitmap + i * J.getWidth();
148 if (checkSSE2 && I.
getWidth() >= 16) {
149 for (; j <= I.
getWidth() - 16; j += 16) {
150 __m128i m = _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[0]));
151 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[1])));
152 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[2])));
153 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[3])));
154 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[4])));
155 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[5])));
156 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[6])));
157 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[7])));
158 m = _mm_min_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[8])));
160 _mm_storeu_si128((__m128i *)(ptr_curr_I + j), m);
166 unsigned char min_value = null_value;
167 for (
int k = 0; k < 9; k++) {
168 min_value = (std::min)(min_value, *(ptr_curr_J + j + offset[k]));
171 *(ptr_curr_I + j) = min_value;
203 std::cerr <<
"Input image is empty!" << std::endl;
207 const unsigned char null_value = 0;
211 for (
unsigned int i = 0; i < J.getHeight(); i++) {
212 if (i == 0 || i == J.getHeight() - 1) {
213 for (
unsigned int j = 0; j < J.getWidth(); j++) {
214 J[i][j] = null_value;
217 J[i][0] = null_value;
218 memcpy(J[i] + 1, I[i - 1],
sizeof(
unsigned char) * I.
getWidth());
219 J[i][J.getWidth() - 1] = null_value;
224 unsigned int offset[5] = {1, J.
getWidth(), J.getWidth() + 1, J.getWidth() + 2, J.getWidth() * 2 + 1};
229 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
231 unsigned char *ptr_curr_J = J.bitmap + i * J.getWidth();
235 if (checkSSE2 && I.
getWidth() >= 16) {
236 for (; j <= I.
getWidth() - 16; j += 16) {
237 __m128i m = _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[0]));
238 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[1])));
239 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[2])));
240 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[3])));
241 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[4])));
243 _mm_storeu_si128((__m128i *)(ptr_curr_I + j), m);
249 unsigned char max_value = null_value;
250 for (
int k = 0; k < 5; k++) {
251 max_value = (std::max)(max_value, *(ptr_curr_J + j + offset[k]));
254 *(ptr_curr_I + j) = max_value;
259 unsigned int offset[9] = {0,
266 J.getWidth() * 2 + 1,
267 J.getWidth() * 2 + 2};
272 for (
unsigned int i = 0; i < I.
getHeight(); i++) {
274 unsigned char *ptr_curr_J = J.bitmap + i * J.getWidth();
278 if (checkSSE2 && I.
getWidth() >= 16) {
279 for (; j <= I.
getWidth() - 16; j += 16) {
280 __m128i m = _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[0]));
281 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[1])));
282 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[2])));
283 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[3])));
284 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[4])));
285 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[5])));
286 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[6])));
287 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[7])));
288 m = _mm_max_epu8(m, _mm_loadu_si128((
const __m128i *)(ptr_curr_J + j + offset[8])));
290 _mm_storeu_si128((__m128i *)(ptr_curr_I + j), m);
296 unsigned char max_value = null_value;
297 for (
int k = 0; k < 9; k++) {
298 max_value = (std::max)(max_value, *(ptr_curr_J + j + offset[k]));
301 *(ptr_curr_I + j) = max_value;
static void dilatation(vpImage< Type > &I, Type value, Type value_out, vpConnexityType connexity=CONNEXITY_4)
unsigned int getWidth() const
Type * bitmap
points toward the bitmap
static void erosion(vpImage< Type > &I, Type value, Type value_out, vpConnexityType connexity=CONNEXITY_4)
unsigned int getSize() const
VISP_EXPORT bool checkSSE2()
unsigned int getHeight() const