title: Laplacian of Gaussian Edge Detector Being Affected by Change of Mask Size
body: <p>For a class, I've written a <a href="https://softwareengineering.stackexchange.com/questions/233876/comparing-absolute-values-when-determining-zero-crossing-in-2d-image">Laplacian of Gaussian edge detector</a> that works in the following way.</p>
  
  <ol>
  <li>Make a Laplacian of Gaussian mask given the variance of the Gaussian the size of the mask</li>
  <li>Convolve it with the image</li>
  <li>Find the zero crossings in a really shoddy manner, these are the edges of the image</li>
  </ol>
  
  <p>If you so desire, the code for this program can be viewed <a href="https://gist.github.com/Seanny123/10452462" rel="nofollow noreferrer">here</a>, but the most important part is where I create my Gaussian mask which depends on two functions that I've reproduced here for your convenience:</p>
  
  <pre><code># Function for calculating the laplacian of the gaussian at a given point and with a given variance
  def l_o_g(x, y, sigma):
      # Formatted this way for readability
      nom = ( (y**2)+(x**2)-2*(sigma**2) )
      denom = ( (2*math.pi*(sigma**6) ))
      expo = math.exp( -((x**2)+(y**2))/(2*(sigma**2)) )
      return nom*expo/denom
  
  
  # Create the laplacian of the gaussian, given a sigma
  # Note the recommended size is 7 according to this website http://homepages.inf.ed.ac.uk/rbf/HIPR2/log.htm 
  # Experimentally, I've found 6 to be much more reliable for images with clear edges and 4 to be better for images with a lot of little edges
  def create_log(sigma, size = 7):
      w = math.ceil(float(size)*float(sigma))
  
      # If the dimension is an even number, make it uneven
      if(w%2 == 0):
          print "even number detected, incrementing"
          w = w + 1
  
      # Now make the mask
      l_o_g_mask = []
  
      w_range = int(math.floor(w/2))
      print "Going from " + str(-w_range) + " to " + str(w_range)
      for i in range_inc(-w_range, w_range):
          for j in range_inc(-w_range, w_range):
              l_o_g_mask.append(l_o_g(i,j,sigma))
      l_o_g_mask = np.array(l_o_g_mask)
      l_o_g_mask = l_o_g_mask.reshape(w,w)
      return l_o_g_mask
  </code></pre>
  
  <p>All in all, it works relatively well, even if it is extremely slow because I <a href="https://codereview.stackexchange.com/questions/45458/finding-a-zero-crossing-in-a-matrix">don't know how to leverage Numpy</a>. However, whenever I change the size of the Gaussian mask, the thickness of the edges I detect change drastically.</p>
  
  <p>Here is the image run with a size of mask equivalent to 4 times the given variance of the Gaussian:
  <img src="https://i.stack.imgur.com/dqOzi.png" alt="4 times the variance"></p>
  
  <p>Here is the same image run with a size of mask equivalent to 6 times the variance:
  <img src="https://i.stack.imgur.com/kuPqk.png" alt="6 times the variance"></p>
  
  <p>I'm kind of baffled, because the only thing the <code>size</code> parameter should change is the accuracy of the approximation of the Laplacian of Gaussian mask before I begin to convolve it with the image. So I ran <a href="https://gist.github.com/Seanny123/10452919" rel="nofollow noreferrer">a test</a> where I wanted to vizualize how my mask looked given different size parameters.</p>
  
  <p>Here it is with a size of 4:
  <img src="https://i.stack.imgur.com/1YnCy.png" alt="4_l_o_g"></p>
  
  <p>Here it is with a size of 6:
  <img src="https://i.stack.imgur.com/JrBzD.png" alt="6_l_o_g"></p>
  
  <p>The shape of the function seems to be the same as far as I can tell from the zero crossings (they happen to be spaced around four pixels apart) and their peaks. Is there a better way to check?</p>
  
  <p>Any suggestions as to why this issue might be occurring or how to investigate further are appreciated.</p>