title: How to determine edges in an image optimally?
body: <p>I recently was put in front of the problem of cropping and resizing images. I needed to crop the 'main content' of an image for example if i had an image similar to this: <a href="https://i.stack.imgur.com/vNoAK.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/vNoAK.jpg" alt="alt text"></a><br>
  <sub>(source: <a href="http://blstb.msn.com/i/8C/10F73EB7EE231B1EA8E65EFA7D69B.jpg" rel="nofollow noreferrer">msn.com</a>)</sub>  </p>
  
  <p>the result should be an image with the msn content without the white margins(left&amp; right).</p>
  
  <p>I search on the X axis for the first and last color change and on the Y axis the same thing. The problem is that traversing the image line by line takes a while..for an image that is 2000x1600px it takes up to 2 seconds to return the CropRect => x1,y1,x2,y2 data.</p>
  
  <p>I tried to make for each coordinate a traversal and stop on the first value found but it didn't work in all test cases..sometimes the returned data wasn't the expected one and the duration of the operations was similar..</p>
  
  <p>Any idea how to cut down the traversal time and discovery of the rectangle round the 'main content'?</p>
  
  <pre><code>public static CropRect EdgeDetection(Bitmap Image, float Threshold)
          {
              CropRect cropRectangle = new CropRect();
              int lowestX = 0;
              int lowestY = 0;
              int largestX = 0;
              int largestY = 0;
  
              lowestX = Image.Width;
              lowestY = Image.Height;
  
              //find the lowest X bound;
              for (int y = 0; y &lt; Image.Height - 1; ++y)
              {
                  for (int x = 0; x &lt; Image.Width - 1; ++x)
                  {
                      Color currentColor = Image.GetPixel(x, y);
                      Color tempXcolor = Image.GetPixel(x + 1, y);
                      Color tempYColor = Image.GetPixel(x, y + 1);
                      if ((Math.Sqrt(((currentColor.R - tempXcolor.R) * (currentColor.R - tempXcolor.R)) +
                          ((currentColor.G - tempXcolor.G) * (currentColor.G - tempXcolor.G)) +
                          ((currentColor.B - tempXcolor.B) * (currentColor.B - tempXcolor.B))) &gt; Threshold)) 
                      {
                          if (lowestX &gt; x)
                              lowestX = x;
  
                          if (largestX &lt; x)
                              largestX = x;
                      }
  
                      if ((Math.Sqrt(((currentColor.R - tempYColor.R) * (currentColor.R - tempYColor.R)) +
                          ((currentColor.G - tempYColor.G) * (currentColor.G - tempYColor.G)) +
                          ((currentColor.B - tempYColor.B) * (currentColor.B - tempYColor.B))) &gt; Threshold))
                      {
                          if (lowestY &gt; y)
                              lowestY = y;
  
                          if (largestY &lt; y)
                              largestY = y;
                      }
                  }                
              }
  
              if (lowestX &lt; Image.Width / 4)
                  cropRectangle.X = lowestX - 3 &gt; 0 ? lowestX - 3 : 0;
              else
                  cropRectangle.X = 0;
  
              if (lowestY &lt; Image.Height / 4)
                  cropRectangle.Y = lowestY - 3 &gt; 0 ? lowestY - 3 : 0;
              else
                  cropRectangle.Y = 0;
  
              cropRectangle.Width = largestX - lowestX + 8 &gt; Image.Width ? Image.Width : largestX - lowestX + 8;
              cropRectangle.Height = largestY + 8 &gt; Image.Height ? Image.Height - lowestY : largestY - lowestY + 8;
              return cropRectangle;
          }
      }
  </code></pre>