Skip to content
Snippets Groups Projects
edge_detection.jn 5.19 KiB
Newer Older
  • Learn to ignore specific revisions
  • rarbore2's avatar
    rarbore2 committed
    const gs : usize = 7;
    const sz : usize = 3;
    const sb : usize = 3;
    
    fn gaussian_smoothing<n, m : usize>(
    
    Aaron Councilman's avatar
    Aaron Councilman committed
      input: f32[n, m],
    
    rarbore2's avatar
    rarbore2 committed
      filter: f32[7, 7],
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    ) -> f32[n, m] {
    
    rarbore2's avatar
    rarbore2 committed
      @res let result : f32[n, m];
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    
      // Define the gaussian radius as half the gaussian size
      const gr = gs / 2;
    
    
    rarbore2's avatar
    rarbore2 committed
      @image_loop for row = 0 to n {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
        for col = 0 to m {
          let smoothed = 0.0;
    
    
    rarbore2's avatar
    rarbore2 committed
          @filter_loop for i = 0 to gs {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            for j = 0 to gs {
    
    rarbore2's avatar
    rarbore2 committed
              let br = min!(max!(row + i, gr) - gr, n - 1);
              let bc = min!(max!(col + j, gr) - gr, m - 1);
              let val = input[br, bc];
    
    Aaron Councilman's avatar
    Aaron Councilman committed
              smoothed += val * filter[i, j];
            }
          }
    
          result[row, col] = smoothed;
        }
      }
    
      return result;
    }
    
    const MIN_BR : f32 = 0;
    const MAX_BR : f32 = 1;
    
    
    rarbore2's avatar
    rarbore2 committed
    fn laplacian_estimate<n, m : usize>(
    
    Aaron Councilman's avatar
    Aaron Councilman committed
      input: f32[n, m],
    
    rarbore2's avatar
    rarbore2 committed
      structure: f32[3, 3],
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    ) -> f32[n, m] {
      const r = sz / 2;
    
    
    rarbore2's avatar
    rarbore2 committed
      @res let result : f32[n, m];
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    
    
    rarbore2's avatar
    rarbore2 committed
      @image_loop for row = 0 to n {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
        for col = 0 to m {
          // Compute pixel of dilated image
          let dilated = MIN_BR;
    
    rarbore2's avatar
    rarbore2 committed
          @filter_loop for i = 0 to sz {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            for j = 0 to sz {
    
    rarbore2's avatar
    rarbore2 committed
    	  let filter = if row + i < r
                             || row + i - r > n - 1
                             || col + j < r
                             || col + j - r > m - 1 then MIN_BR
                          else input[row + i - r, col + j - r];
              dilated = max!(dilated, filter * structure[i, j]);
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            }
          }
    
          // Compute pixel of eroded image
          let eroded = MAX_BR;
    
    rarbore2's avatar
    rarbore2 committed
          @filter_loop for i = 0 to sz {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            for j = 0 to sz {
    
    rarbore2's avatar
    rarbore2 committed
    	  let filter = if row + i < r
                             || row + i - r > n - 1
                             || col + j < r
                             || col + j - r > m - 1 then MAX_BR
                          else input[row + i - r, col + j - r];
              eroded = min!(eroded, filter * structure[i, j]);
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            }
          }
    
          let laplacian = dilated + eroded - 2 * input[row, col];
          result[row, col] = laplacian;
        }
      }
    
      return result;
    }
    
    
    rarbore2's avatar
    rarbore2 committed
    fn zero_crossings<n, m : usize>(
    
    Aaron Councilman's avatar
    Aaron Councilman committed
      input: f32[n, m],
    
    rarbore2's avatar
    rarbore2 committed
      structure: f32[3, 3],
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    ) -> f32[n, m] {
      const r = sz / 2;
    
    
    rarbore2's avatar
    rarbore2 committed
      @res let result : f32[n, m];
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    
    
    rarbore2's avatar
    rarbore2 committed
      @image_loop for row = 0 to n {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
        for col = 0 to m {
          // Compute the pixel of dilated image
          let dilated = MIN_BR;
    
    rarbore2's avatar
    rarbore2 committed
          @filter_loop for i = 0 to sz {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            for j = 0 to sz {
    
    rarbore2's avatar
    rarbore2 committed
    	  let filter = if row + i < r
                              || row + i - r > n - 1
                              || col + j < r
                              || col + j - r > m - 1 then MIN_BR
                           else if input[row + i - r, col + j - r] > MIN_BR then MAX_BR
                           else MIN_BR;
              dilated = max!(dilated, filter * structure[i, j]);
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            }
          }
    
          // Compute the pixel of eroded image
          let eroded = MAX_BR;
    
    rarbore2's avatar
    rarbore2 committed
          @filter_loop for i = 0 to sz {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            for j = 0 to sz {
    
    rarbore2's avatar
    rarbore2 committed
    	  let filter = if row + i < r
                              || row + i - r > n - 1
                              || col + j < r
                              || col + j - r > m - 1 then MAX_BR
                           else if input[row + i - r, col + j - r] > MIN_BR then MAX_BR
                           else MIN_BR;
              eroded = min!(eroded, filter * structure[i, j]);
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            }
          }
    
          let sign = dilated - eroded;
          result[row, col] = sign;
        }
      }
    
      return result;
    }
    
    
    rarbore2's avatar
    rarbore2 committed
    fn gradient<n, m : usize>(
    
    Aaron Councilman's avatar
    Aaron Councilman committed
      input: f32[n, m],
    
    rarbore2's avatar
    rarbore2 committed
      sx: f32[3, 3],
      sy: f32[3, 3],
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    ) -> f32[n, m] {
      const sbr = sb / 2;
    
    
    rarbore2's avatar
    rarbore2 committed
      @res let result : f32[n, m];
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    
      for row = 0 to n {
        for col = 0 to m {
    
          let gx = 0;
          let gy = 0;
    
    
    rarbore2's avatar
    rarbore2 committed
          @filter_loop for i = 0 to sb {
    
    Aaron Councilman's avatar
    Aaron Councilman committed
            for j = 0 to sb {
              let val = input[if row + i < sbr              then 0
                              else if row + i - sbr > n - 1 then n - 1
                                                            else row + i - sbr,
                              if col + j < sbr              then 0
                              else if col + j - sbr > m - 1 then m - 1
                                                            else col + j - sbr];
              gx += val * sx[i, j];
              gy += val * sy[i, j];
            }
          }
    
          result[row, col] = sqrt!(gx * gx + gy * gy);
        }
      }
    
      return result;
    }
    
    fn max_gradient<n, m: usize>(gradient: f32[n, m]) -> f32 {
    
    rarbore2's avatar
    rarbore2 committed
      let max = -1.0;
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    
      for i = 0 to n {
        for j = 0 to m {
          max = max!(max, gradient[i, j]);
        }
      }
    
      return max;
    }
    
    fn reject_zero_crossings<n, m: usize>(
      crossings: f32[n, m],
      gradient: f32[n, m],
      max_gradient: f32,
      theta: f32,
    ) -> f32[n, m] {
    
    rarbore2's avatar
    rarbore2 committed
      @res let result : f32[n, m];
    
    Aaron Councilman's avatar
    Aaron Councilman committed
    
      for row = 0 to n {
        for col = 0 to m {
          result[row, col] =
            if crossings[row, col] > 0 && gradient[row, col] > theta * max_gradient
            then 1.0
            else 0.0;
        }
      }
    
      return result;
    }
    
    #[entry]
    
    rarbore2's avatar
    rarbore2 committed
    fn edge_detection<n, m : usize>(
    
    Aaron Councilman's avatar
    Aaron Councilman committed
      input: f32[n, m],
      gaussian_filter: f32[gs, gs],
    
    rarbore2's avatar
    rarbore2 committed
      structure: f32[3, 3],
      sx: f32[3, 3],
      sy: f32[3, 3],
    
    Aaron Councilman's avatar
    Aaron Councilman committed
      theta: f32,
    ) -> f32[n, m] {
    
    rarbore2's avatar
    rarbore2 committed
      let smoothed = gaussian_smoothing::<n, m>(input, gaussian_filter);
      @le let laplacian = laplacian_estimate::<n, m>(smoothed, structure);
      @zc let zcs = zero_crossings::<n, m>(laplacian, structure);
      let gradient = gradient::<n, m>(smoothed, sx, sy);
    
    rarbore2's avatar
    rarbore2 committed
      let maxgrad = max_gradient::<n, m>(gradient);
    
    Aaron Councilman's avatar
    Aaron Councilman committed
      return reject_zero_crossings::<n, m>(zcs, gradient, maxgrad, theta);
    }