Home | History | Annotate | Download | only in cuda
      1 /*M///////////////////////////////////////////////////////////////////////////////////////
      2 //
      3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
      4 //
      5 //  By downloading, copying, installing or using the software you agree to this license.
      6 //  If you do not agree to this license, do not download, install,
      7 //  copy or use the software.
      8 //
      9 //
     10 //                           License Agreement
     11 //                For Open Source Computer Vision Library
     12 //
     13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
     14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
     15 // Third party copyrights are property of their respective owners.
     16 //
     17 // Redistribution and use in source and binary forms, with or without modification,
     18 // are permitted provided that the following conditions are met:
     19 //
     20 //   * Redistribution's of source code must retain the above copyright notice,
     21 //     this list of conditions and the following disclaimer.
     22 //
     23 //   * Redistribution's in binary form must reproduce the above copyright notice,
     24 //     this list of conditions and the following disclaimer in the documentation
     25 //     and/or other materials provided with the distribution.
     26 //
     27 //   * The name of the copyright holders may not be used to endorse or promote products
     28 //     derived from this software without specific prior written permission.
     29 //
     30 // This software is provided by the copyright holders and contributors "as is" and
     31 // any express or implied warranties, including, but not limited to, the implied
     32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
     33 // In no event shall the Intel Corporation or contributors be liable for any direct,
     34 // indirect, incidental, special, exemplary, or consequential damages
     35 // (including, but not limited to, procurement of substitute goods or services;
     36 // loss of use, data, or profits; or business interruption) however caused
     37 // and on any theory of liability, whether in contract, strict liability,
     38 // or tort (including negligence or otherwise) arising in any way out of
     39 // the use of this software, even if advised of the possibility of such damage.
     40 //
     41 //M*/
     42 
     43 #if !defined CUDA_DISABLER
     44 
     45 #include "opencv2/core/cuda/common.hpp"
     46 #include "opencv2/core/cuda/vec_math.hpp"
     47 
     48 namespace cv { namespace cuda { namespace device
     49 {
     50     namespace hough_segments
     51     {
     52         __device__ int g_counter;
     53 
     54         texture<uchar, cudaTextureType2D, cudaReadModeElementType> tex_mask(false, cudaFilterModePoint, cudaAddressModeClamp);
     55 
     56         __global__ void houghLinesProbabilistic(const PtrStepSzi accum,
     57                                                 int4* out, const int maxSize,
     58                                                 const float rho, const float theta,
     59                                                 const int lineGap, const int lineLength,
     60                                                 const int rows, const int cols)
     61         {
     62             const int r = blockIdx.x * blockDim.x + threadIdx.x;
     63             const int n = blockIdx.y * blockDim.y + threadIdx.y;
     64 
     65             if (r >= accum.cols - 2 || n >= accum.rows - 2)
     66                 return;
     67 
     68             const int curVotes = accum(n + 1, r + 1);
     69 
     70             if (curVotes >= lineLength &&
     71                 curVotes > accum(n, r) &&
     72                 curVotes > accum(n, r + 1) &&
     73                 curVotes > accum(n, r + 2) &&
     74                 curVotes > accum(n + 1, r) &&
     75                 curVotes > accum(n + 1, r + 2) &&
     76                 curVotes > accum(n + 2, r) &&
     77                 curVotes > accum(n + 2, r + 1) &&
     78                 curVotes > accum(n + 2, r + 2))
     79             {
     80                 const float radius = (r - (accum.cols - 2 - 1) * 0.5f) * rho;
     81                 const float angle = n * theta;
     82 
     83                 float cosa;
     84                 float sina;
     85                 sincosf(angle, &sina, &cosa);
     86 
     87                 float2 p0 = make_float2(cosa * radius, sina * radius);
     88                 float2 dir = make_float2(-sina, cosa);
     89 
     90                 float2 pb[4] = {make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1), make_float2(-1, -1)};
     91                 float a;
     92 
     93                 if (dir.x != 0)
     94                 {
     95                     a = -p0.x / dir.x;
     96                     pb[0].x = 0;
     97                     pb[0].y = p0.y + a * dir.y;
     98 
     99                     a = (cols - 1 - p0.x) / dir.x;
    100                     pb[1].x = cols - 1;
    101                     pb[1].y = p0.y + a * dir.y;
    102                 }
    103                 if (dir.y != 0)
    104                 {
    105                     a = -p0.y / dir.y;
    106                     pb[2].x = p0.x + a * dir.x;
    107                     pb[2].y = 0;
    108 
    109                     a = (rows - 1 - p0.y) / dir.y;
    110                     pb[3].x = p0.x + a * dir.x;
    111                     pb[3].y = rows - 1;
    112                 }
    113 
    114                 if (pb[0].x == 0 && (pb[0].y >= 0 && pb[0].y < rows))
    115                 {
    116                     p0 = pb[0];
    117                     if (dir.x < 0)
    118                         dir = -dir;
    119                 }
    120                 else if (pb[1].x == cols - 1 && (pb[1].y >= 0 && pb[1].y < rows))
    121                 {
    122                     p0 = pb[1];
    123                     if (dir.x > 0)
    124                         dir = -dir;
    125                 }
    126                 else if (pb[2].y == 0 && (pb[2].x >= 0 && pb[2].x < cols))
    127                 {
    128                     p0 = pb[2];
    129                     if (dir.y < 0)
    130                         dir = -dir;
    131                 }
    132                 else if (pb[3].y == rows - 1 && (pb[3].x >= 0 && pb[3].x < cols))
    133                 {
    134                     p0 = pb[3];
    135                     if (dir.y > 0)
    136                         dir = -dir;
    137                 }
    138 
    139                 float2 d;
    140                 if (::fabsf(dir.x) > ::fabsf(dir.y))
    141                 {
    142                     d.x = dir.x > 0 ? 1 : -1;
    143                     d.y = dir.y / ::fabsf(dir.x);
    144                 }
    145                 else
    146                 {
    147                     d.x = dir.x / ::fabsf(dir.y);
    148                     d.y = dir.y > 0 ? 1 : -1;
    149                 }
    150 
    151                 float2 line_end[2];
    152                 int gap;
    153                 bool inLine = false;
    154 
    155                 float2 p1 = p0;
    156                 if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows)
    157                     return;
    158 
    159                 for (;;)
    160                 {
    161                     if (tex2D(tex_mask, p1.x, p1.y))
    162                     {
    163                         gap = 0;
    164 
    165                         if (!inLine)
    166                         {
    167                             line_end[0] = p1;
    168                             line_end[1] = p1;
    169                             inLine = true;
    170                         }
    171                         else
    172                         {
    173                             line_end[1] = p1;
    174                         }
    175                     }
    176                     else if (inLine)
    177                     {
    178                         if (++gap > lineGap)
    179                         {
    180                             bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength ||
    181                                              ::abs(line_end[1].y - line_end[0].y) >= lineLength;
    182 
    183                             if (good_line)
    184                             {
    185                                 const int ind = ::atomicAdd(&g_counter, 1);
    186                                 if (ind < maxSize)
    187                                     out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y);
    188                             }
    189 
    190                             gap = 0;
    191                             inLine = false;
    192                         }
    193                     }
    194 
    195                     p1 = p1 + d;
    196                     if (p1.x < 0 || p1.x >= cols || p1.y < 0 || p1.y >= rows)
    197                     {
    198                         if (inLine)
    199                         {
    200                             bool good_line = ::abs(line_end[1].x - line_end[0].x) >= lineLength ||
    201                                              ::abs(line_end[1].y - line_end[0].y) >= lineLength;
    202 
    203                             if (good_line)
    204                             {
    205                                 const int ind = ::atomicAdd(&g_counter, 1);
    206                                 if (ind < maxSize)
    207                                     out[ind] = make_int4(line_end[0].x, line_end[0].y, line_end[1].x, line_end[1].y);
    208                             }
    209 
    210                         }
    211                         break;
    212                     }
    213                 }
    214             }
    215         }
    216 
    217         int houghLinesProbabilistic_gpu(PtrStepSzb mask, PtrStepSzi accum, int4* out, int maxSize, float rho, float theta, int lineGap, int lineLength)
    218         {
    219             void* counterPtr;
    220             cudaSafeCall( cudaGetSymbolAddress(&counterPtr, g_counter) );
    221 
    222             cudaSafeCall( cudaMemset(counterPtr, 0, sizeof(int)) );
    223 
    224             const dim3 block(32, 8);
    225             const dim3 grid(divUp(accum.cols - 2, block.x), divUp(accum.rows - 2, block.y));
    226 
    227             bindTexture(&tex_mask, mask);
    228 
    229             houghLinesProbabilistic<<<grid, block>>>(accum,
    230                                                      out, maxSize,
    231                                                      rho, theta,
    232                                                      lineGap, lineLength,
    233                                                      mask.rows, mask.cols);
    234             cudaSafeCall( cudaGetLastError() );
    235 
    236             cudaSafeCall( cudaDeviceSynchronize() );
    237 
    238             int totalCount;
    239             cudaSafeCall( cudaMemcpy(&totalCount, counterPtr, sizeof(int), cudaMemcpyDeviceToHost) );
    240 
    241             totalCount = ::min(totalCount, maxSize);
    242 
    243             return totalCount;
    244         }
    245     }
    246 }}}
    247 
    248 
    249 #endif /* CUDA_DISABLER */
    250