Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of gr-peach-opencv-project-sd-card by
spatialgradient.cpp
00001 /*M/////////////////////////////////////////////////////////////////////////////////////// 00002 // 00003 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. 00004 // 00005 // By downloading, copying, installing or using the software you agree to this license. 00006 // If you do not agree to this license, do not download, install, 00007 // copy or use the software. 00008 // 00009 // 00010 // License Agreement 00011 // For Open Source Computer Vision Library 00012 // 00013 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved. 00014 // Copyright (C) 2009, Willow Garage Inc., all rights reserved. 00015 // Third party copyrights are property of their respective owners. 00016 // 00017 // Redistribution and use in source and binary forms, with or without modification, 00018 // are permitted provided that the following conditions are met: 00019 // 00020 // * Redistribution's of source code must retain the above copyright notice, 00021 // this list of conditions and the following disclaimer. 00022 // 00023 // * Redistribution's in binary form must reproduce the above copyright notice, 00024 // this list of conditions and the following disclaimer in the documentation 00025 // and/or other materials provided with the distribution. 00026 // 00027 // * The name of the copyright holders may not be used to endorse or promote products 00028 // derived from this software without specific prior written permission. 00029 // 00030 // This software is provided by the copyright holders and contributors "as is" and 00031 // any express or implied warranties, including, but not limited to, the implied 00032 // warranties of merchantability and fitness for a particular purpose are disclaimed. 00033 // In no event shall the Intel Corporation or contributors be liable for any direct, 00034 // indirect, incidental, special, exemplary, or consequential damages 00035 // (including, but not limited to, procurement of substitute goods or services; 00036 // loss of use, data, or profits; or business interruption) however caused 00037 // and on any theory of liability, whether in contract, strict liability, 00038 // or tort (including negligence or otherwise) arising in any way out of 00039 // the use of this software, even if advised of the possibility of such damage. 00040 // 00041 //M*/ 00042 00043 #include "precomp.hpp" 00044 #include "opencv2/core/hal/intrin.hpp" 00045 00046 #include <iostream> 00047 namespace cv 00048 { 00049 00050 /* NOTE: 00051 * 00052 * Sobel-x: -1 0 1 00053 * -2 0 2 00054 * -1 0 1 00055 * 00056 * Sobel-y: -1 -2 -1 00057 * 0 0 0 00058 * 1 2 1 00059 */ 00060 template <typename T> 00061 static inline void spatialGradientKernel( T& vx, T& vy, 00062 const T& v00, const T& v01, const T& v02, 00063 const T& v10, const T& v12, 00064 const T& v20, const T& v21, const T& v22 ) 00065 { 00066 // vx = (v22 - v00) + (v02 - v20) + 2 * (v12 - v10) 00067 // vy = (v22 - v00) + (v20 - v02) + 2 * (v21 - v01) 00068 00069 T tmp_add = v22 - v00, 00070 tmp_sub = v02 - v20, 00071 tmp_x = v12 - v10, 00072 tmp_y = v21 - v01; 00073 00074 vx = tmp_add + tmp_sub + tmp_x + tmp_x; 00075 vy = tmp_add - tmp_sub + tmp_y + tmp_y; 00076 } 00077 00078 void spatialGradient( InputArray _src, OutputArray _dx, OutputArray _dy, 00079 int ksize, int borderType ) 00080 { 00081 00082 // Prepare InputArray src 00083 Mat src = _src.getMat(); 00084 CV_Assert( !src.empty() ); 00085 CV_Assert( src.type() == CV_8UC1 ); 00086 CV_Assert( borderType == BORDER_DEFAULT || borderType == BORDER_REPLICATE ); 00087 00088 // Prepare OutputArrays dx, dy 00089 _dx.create( src.size(), CV_16SC1 ); 00090 _dy.create( src.size(), CV_16SC1 ); 00091 Mat dx = _dx.getMat(), 00092 dy = _dy.getMat(); 00093 00094 // TODO: Allow for other kernel sizes 00095 CV_Assert(ksize == 3); 00096 00097 // Get dimensions 00098 const int H = src.rows, 00099 W = src.cols; 00100 00101 // Row, column indices 00102 int i = 0, 00103 j = 0; 00104 00105 // Handle border types 00106 int i_top = 0, // Case for H == 1 && W == 1 && BORDER_REPLICATE 00107 i_bottom = H - 1, 00108 j_offl = 0, // j offset from 0th pixel to reach -1st pixel 00109 j_offr = 0; // j offset from W-1th pixel to reach Wth pixel 00110 00111 if ( borderType == BORDER_DEFAULT ) // Equiv. to BORDER_REFLECT_101 00112 { 00113 if ( H > 1 ) 00114 { 00115 i_top = 1; 00116 i_bottom = H - 2; 00117 } 00118 if ( W > 1 ) 00119 { 00120 j_offl = 1; 00121 j_offr = -1; 00122 } 00123 } 00124 00125 // Pointer to row vectors 00126 uchar *p_src, *c_src, *n_src; // previous, current, next row 00127 short *c_dx, *c_dy; 00128 00129 int i_start = 0; 00130 int j_start = 0; 00131 #if CV_SIMD128 && CV_SSE2 00132 uchar *m_src; 00133 short *n_dx, *n_dy; 00134 00135 // Characters in variable names have the following meanings: 00136 // u: unsigned char 00137 // s: signed int 00138 // 00139 // [row][column] 00140 // m: offset -1 00141 // n: offset 0 00142 // p: offset 1 00143 // Example: umn is offset -1 in row and offset 0 in column 00144 for ( i = 0; i < H - 1; i += 2 ) 00145 { 00146 if ( i == 0 ) p_src = src.ptr<uchar>(i_top); 00147 else p_src = src.ptr<uchar>(i-1); 00148 00149 c_src = src.ptr<uchar>(i); 00150 n_src = src.ptr<uchar>(i+1); 00151 00152 if ( i == H - 2 ) m_src = src.ptr<uchar>(i_bottom); 00153 else m_src = src.ptr<uchar>(i+2); 00154 00155 c_dx = dx.ptr<short>(i); 00156 c_dy = dy.ptr<short>(i); 00157 n_dx = dx.ptr<short>(i+1); 00158 n_dy = dy.ptr<short>(i+1); 00159 00160 v_uint8x16 v_select_m = v_uint8x16(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 00161 0, 0, 0, 0xFF); 00162 00163 // Process rest of columns 16-column chunks at a time 00164 for ( j = 1; j < W - 16; j += 16 ) 00165 { 00166 // Load top row for 3x3 Sobel filter 00167 v_uint8x16 v_um = v_load(&p_src[j-1]); 00168 v_uint8x16 v_up = v_load(&p_src[j+1]); 00169 // TODO: Replace _mm_slli_si128 with hal method 00170 v_uint8x16 v_un = v_select(v_select_m, v_uint8x16(_mm_slli_si128(v_up.val, 1)), 00171 v_uint8x16(_mm_srli_si128(v_um.val, 1))); 00172 v_uint16x8 v_um1, v_um2, v_un1, v_un2, v_up1, v_up2; 00173 v_expand(v_um, v_um1, v_um2); 00174 v_expand(v_un, v_un1, v_un2); 00175 v_expand(v_up, v_up1, v_up2); 00176 v_int16x8 v_s1m1 = v_reinterpret_as_s16(v_um1); 00177 v_int16x8 v_s1m2 = v_reinterpret_as_s16(v_um2); 00178 v_int16x8 v_s1n1 = v_reinterpret_as_s16(v_un1); 00179 v_int16x8 v_s1n2 = v_reinterpret_as_s16(v_un2); 00180 v_int16x8 v_s1p1 = v_reinterpret_as_s16(v_up1); 00181 v_int16x8 v_s1p2 = v_reinterpret_as_s16(v_up2); 00182 00183 // Load second row for 3x3 Sobel filter 00184 v_um = v_load(&c_src[j-1]); 00185 v_up = v_load(&c_src[j+1]); 00186 // TODO: Replace _mm_slli_si128 with hal method 00187 v_un = v_select(v_select_m, v_uint8x16(_mm_slli_si128(v_up.val, 1)), 00188 v_uint8x16(_mm_srli_si128(v_um.val, 1))); 00189 v_expand(v_um, v_um1, v_um2); 00190 v_expand(v_un, v_un1, v_un2); 00191 v_expand(v_up, v_up1, v_up2); 00192 v_int16x8 v_s2m1 = v_reinterpret_as_s16(v_um1); 00193 v_int16x8 v_s2m2 = v_reinterpret_as_s16(v_um2); 00194 v_int16x8 v_s2n1 = v_reinterpret_as_s16(v_un1); 00195 v_int16x8 v_s2n2 = v_reinterpret_as_s16(v_un2); 00196 v_int16x8 v_s2p1 = v_reinterpret_as_s16(v_up1); 00197 v_int16x8 v_s2p2 = v_reinterpret_as_s16(v_up2); 00198 00199 // Load third row for 3x3 Sobel filter 00200 v_um = v_load(&n_src[j-1]); 00201 v_up = v_load(&n_src[j+1]); 00202 // TODO: Replace _mm_slli_si128 with hal method 00203 v_un = v_select(v_select_m, v_uint8x16(_mm_slli_si128(v_up.val, 1)), 00204 v_uint8x16(_mm_srli_si128(v_um.val, 1))); 00205 v_expand(v_um, v_um1, v_um2); 00206 v_expand(v_un, v_un1, v_un2); 00207 v_expand(v_up, v_up1, v_up2); 00208 v_int16x8 v_s3m1 = v_reinterpret_as_s16(v_um1); 00209 v_int16x8 v_s3m2 = v_reinterpret_as_s16(v_um2); 00210 v_int16x8 v_s3n1 = v_reinterpret_as_s16(v_un1); 00211 v_int16x8 v_s3n2 = v_reinterpret_as_s16(v_un2); 00212 v_int16x8 v_s3p1 = v_reinterpret_as_s16(v_up1); 00213 v_int16x8 v_s3p2 = v_reinterpret_as_s16(v_up2); 00214 00215 // dx & dy for rows 1, 2, 3 00216 v_int16x8 v_sdx1, v_sdy1; 00217 spatialGradientKernel<v_int16x8>( v_sdx1, v_sdy1, 00218 v_s1m1, v_s1n1, v_s1p1, 00219 v_s2m1, v_s2p1, 00220 v_s3m1, v_s3n1, v_s3p1 ); 00221 00222 v_int16x8 v_sdx2, v_sdy2; 00223 spatialGradientKernel<v_int16x8>( v_sdx2, v_sdy2, 00224 v_s1m2, v_s1n2, v_s1p2, 00225 v_s2m2, v_s2p2, 00226 v_s3m2, v_s3n2, v_s3p2 ); 00227 00228 // Store 00229 v_store(&c_dx[j], v_sdx1); 00230 v_store(&c_dx[j+8], v_sdx2); 00231 v_store(&c_dy[j], v_sdy1); 00232 v_store(&c_dy[j+8], v_sdy2); 00233 00234 // Load fourth row for 3x3 Sobel filter 00235 v_um = v_load(&m_src[j-1]); 00236 v_up = v_load(&m_src[j+1]); 00237 // TODO: Replace _mm_slli_si128 with hal method 00238 v_un = v_select(v_select_m, v_uint8x16(_mm_slli_si128(v_up.val, 1)), 00239 v_uint8x16(_mm_srli_si128(v_um.val, 1))); 00240 v_expand(v_um, v_um1, v_um2); 00241 v_expand(v_un, v_un1, v_un2); 00242 v_expand(v_up, v_up1, v_up2); 00243 v_int16x8 v_s4m1 = v_reinterpret_as_s16(v_um1); 00244 v_int16x8 v_s4m2 = v_reinterpret_as_s16(v_um2); 00245 v_int16x8 v_s4n1 = v_reinterpret_as_s16(v_un1); 00246 v_int16x8 v_s4n2 = v_reinterpret_as_s16(v_un2); 00247 v_int16x8 v_s4p1 = v_reinterpret_as_s16(v_up1); 00248 v_int16x8 v_s4p2 = v_reinterpret_as_s16(v_up2); 00249 00250 // dx & dy for rows 2, 3, 4 00251 spatialGradientKernel<v_int16x8>( v_sdx1, v_sdy1, 00252 v_s2m1, v_s2n1, v_s2p1, 00253 v_s3m1, v_s3p1, 00254 v_s4m1, v_s4n1, v_s4p1 ); 00255 00256 spatialGradientKernel<v_int16x8>( v_sdx2, v_sdy2, 00257 v_s2m2, v_s2n2, v_s2p2, 00258 v_s3m2, v_s3p2, 00259 v_s4m2, v_s4n2, v_s4p2 ); 00260 00261 // Store 00262 v_store(&n_dx[j], v_sdx1); 00263 v_store(&n_dx[j+8], v_sdx2); 00264 v_store(&n_dy[j], v_sdy1); 00265 v_store(&n_dy[j+8], v_sdy2); 00266 } 00267 } 00268 i_start = i; 00269 j_start = j; 00270 #endif 00271 int j_p, j_n; 00272 uchar v00, v01, v02, v10, v11, v12, v20, v21, v22; 00273 for ( i = 0; i < H; i++ ) 00274 { 00275 if ( i == 0 ) p_src = src.ptr<uchar>(i_top); 00276 else p_src = src.ptr<uchar>(i-1); 00277 00278 c_src = src.ptr<uchar>(i); 00279 00280 if ( i == H - 1 ) n_src = src.ptr<uchar>(i_bottom); 00281 else n_src = src.ptr<uchar>(i+1); 00282 00283 c_dx = dx.ptr<short>(i); 00284 c_dy = dy.ptr<short>(i); 00285 00286 // Process left-most column 00287 j = 0; 00288 j_p = j + j_offl; 00289 j_n = 1; 00290 if ( j_n >= W ) j_n = j + j_offr; 00291 v00 = p_src[j_p]; v01 = p_src[j]; v02 = p_src[j_n]; 00292 v10 = c_src[j_p]; v11 = c_src[j]; v12 = c_src[j_n]; 00293 v20 = n_src[j_p]; v21 = n_src[j]; v22 = n_src[j_n]; 00294 spatialGradientKernel<short>( c_dx[0], c_dy[0], v00, v01, v02, v10, 00295 v12, v20, v21, v22 ); 00296 v00 = v01; v10 = v11; v20 = v21; 00297 v01 = v02; v11 = v12; v21 = v22; 00298 00299 // Process middle columns 00300 j = i >= i_start ? 1 : j_start; 00301 j_p = j - 1; 00302 v00 = p_src[j_p]; v01 = p_src[j]; 00303 v10 = c_src[j_p]; v11 = c_src[j]; 00304 v20 = n_src[j_p]; v21 = n_src[j]; 00305 00306 for ( ; j < W - 1; j++ ) 00307 { 00308 // Get values for next column 00309 j_n = j + 1; v02 = p_src[j_n]; v12 = c_src[j_n]; v22 = n_src[j_n]; 00310 spatialGradientKernel<short>( c_dx[j], c_dy[j], v00, v01, v02, v10, 00311 v12, v20, v21, v22 ); 00312 00313 // Move values back one column for next iteration 00314 v00 = v01; v10 = v11; v20 = v21; 00315 v01 = v02; v11 = v12; v21 = v22; 00316 } 00317 00318 // Process right-most column 00319 if ( j < W ) 00320 { 00321 j_n = j + j_offr; v02 = p_src[j_n]; v12 = c_src[j_n]; v22 = n_src[j_n]; 00322 spatialGradientKernel<short>( c_dx[j], c_dy[j], v00, v01, v02, v10, 00323 v12, v20, v21, v22 ); 00324 } 00325 } 00326 00327 } 00328 00329 } 00330
Generated on Tue Jul 12 2022 14:47:36 by
1.7.2
