Program: 46628
Project: 46628
Buggy source:
/** 
 * Try to find perforation corners using (modified) Hough transform. After the hough transform, matching pairs of top and bottom corners are found and clustered into pointClusterws list.
 */
void houghTransform(){
  KernelJAI sxKernel=new KernelJAI(3,3,new float[]{-1.0f,0.0f,1.0f,-2.0f,0.0f,2.0f,-1.0f,0.0f,1.0f});
  KernelJAI syKernel=new KernelJAI(3,3,new float[]{-1.0f,-2.0f,-1.0f,0.0f,0.0f,0.0f,1.0f,2.0f,1.0f});
  RenderedImage dblImg=FormatDescriptor.create(stripImage,DataBuffer.TYPE_DOUBLE,null);
  RenderedImage sxImg=ConvolveDescriptor.create(dblImg,sxKernel,null);
  RenderedImage syImg=ConvolveDescriptor.create(dblImg,syKernel,null);
  SampleModel sm=sxImg.getSampleModel();
  int nbands=sm.getNumBands();
  double[] sxPixel=new double[nbands];
  double[] syPixel=new double[nbands];
  Rectangle perfArea=new Rectangle(0,0,stripImage.getWidth() / 4,stripImage.getHeight());
  RectIter sxIter=RectIterFactory.create(sxImg,perfArea);
  RectIter syIter=RectIterFactory.create(syImg,perfArea);
  int width=(int)perfArea.getWidth();
  int height=(int)perfArea.getHeight();
  int accumHeight=(int)maxCornerRadius + 2;
  int[][] startAccum=new int[(int)(maxCornerRadius - minCornerRadius)][width * accumHeight];
  int[][] endAccum=new int[(int)(maxCornerRadius - minCornerRadius)][width * accumHeight];
  byte[] imageDataSingleArray=new byte[width * height];
  DataBufferByte dbuffer=new DataBufferByte(imageDataSingleArray,width * height);
  SampleModel sampleModel=RasterFactory.createBandedSampleModel(DataBuffer.TYPE_BYTE,width,height,1);
  ColorModel colorModel=PlanarImage.createColorModel(sampleModel);
  Raster raster=RasterFactory.createWritableRaster(sampleModel,dbuffer,new Point(0,0));
  List<Point> startCorners=new ArrayList<Point>();
  List<Point> endCorners=new ArrayList<Point>();
  int y=0;
  int maxVal=0;
  if (analysisListener != null) {
    analysisListener.scanAnalysisProgress(0,height);
  }
  while (!sxIter.nextLineDone() && !syIter.nextLineDone()) {
    if (y % 1000 == 0 && y > 0) {
      System.out.println("String_Node_Str" + y + "String_Node_Str");
    }
    sxIter.startPixels();
    syIter.startPixels();
    int x=0;
    while (!sxIter.nextPixelDone() && !syIter.nextPixelDone()) {
      sxIter.getPixel(sxPixel);
      syIter.getPixel(syPixel);
      double isq=sxPixel[0] * sxPixel[0] + syPixel[0] * syPixel[0];
      if (isq > EDGE_MIN_GRADIENT * EDGE_MIN_GRADIENT) {
        if (syPixel[0] <= 0 && sxPixel[0] >= 0) {
          double intensity=Math.sqrt(isq);
          for (double r=minCornerRadius; r < maxCornerRadius; r+=1.0) {
            double cx=(double)x - r * sxPixel[0] / intensity;
            double cy=(double)y - r * syPixel[0] / intensity;
            if (cx > 0.0) {
              int accumLine=(int)cy % accumHeight;
              startAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine]++;
              if (startAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine] > maxVal) {
                maxVal=startAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine];
              }
            }
          }
        }
        if (syPixel[0] >= 0 && sxPixel[0] >= 0) {
          double intensity=Math.sqrt(isq);
          for (double r=minCornerRadius; r < maxCornerRadius; r+=1.0) {
            double cx=(double)x - r * sxPixel[0] / intensity;
            double cy=(double)y - r * syPixel[0] / intensity;
            if (cx > 0.0 && cy > 0.0) {
              int accumLine=(int)cy % accumHeight;
              endAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine]++;
              if (endAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine] > maxVal) {
                maxVal=endAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine];
              }
            }
          }
        }
      }
      x++;
    }
    y++;
    int y2=y - accumHeight;
    int l=y % accumHeight;
    if (y2 > 0) {
      for (int n=0; n < perfArea.getWidth(); n++) {
        for (int r=0; r < (int)(maxCornerRadius - minCornerRadius); r++) {
          if (startAccum[r][n + width * l] >= CORNER_MIN_HOUGH) {
            int val=startAccum[r][n + width * l];
            if (val == getLocalMaxima(startAccum,r,n,y,width)) {
              startCorners.add(new Point(n,y));
              System.out.println(String.format("String_Node_Str",val,r,n,y));
            }
          }
          if (endAccum[r][n + width * l] > CORNER_MIN_HOUGH) {
            int val=endAccum[r][n + width * l];
            if (val == getLocalMaxima(endAccum,r,n,y2,width)) {
              endCorners.add(new Point(n,y2));
              System.out.println(String.format("String_Node_Str",val,r,n,y2));
            }
          }
        }
      }
    }
    for (int n=0; n < perfArea.getWidth(); n++) {
      for (int r=0; r < (int)(maxCornerRadius - minCornerRadius); r++) {
        startAccum[r][n + width * (y % accumHeight)]=0;
        endAccum[r][n + width * (y % accumHeight)]=0;
      }
    }
    if ((y % 100 == 1) && analysisListener != null) {
      analysisListener.scanAnalysisProgress(y - 1,height);
    }
  }
  if (analysisListener != null) {
    analysisListener.scanAnalysisProgress(height,height);
  }
  for (  Point sp : startCorners) {
    for (    Point ep : endCorners) {
      if (ep.y - sp.y > CC_MAX_DIST) {
        break;
      }
      if (Math.abs(ep.x - sp.x) < 10 && ep.y - sp.y > CC_MIN_DIST) {
        Perforation p=new Perforation();
        p.x=(ep.x + sp.x) >> 1;
        p.y=(ep.y + sp.y) >> 1;
        addPointToCluster(p.x,p.y);
      }
    }
  }
  System.out.println(String.format("String_Node_Str",pointClusters.size()));
  for (  PointCluster c : pointClusters) {
    System.out.println(String.format("String_Node_Str",c.getCentroidX(),c.getCentroidY(),c.getPointCount()));
  }
}

Fixed version (ground truth):
/** 
 * Try to find perforation corners using (modified) Hough transform. After the hough transform, matching pairs of top and bottom corners are found and clustered into pointClusterws list.
 */
void houghTransform(){
  KernelJAI sxKernel=new KernelJAI(3,3,new float[]{-1.0f,0.0f,1.0f,-2.0f,0.0f,2.0f,-1.0f,0.0f,1.0f});
  KernelJAI syKernel=new KernelJAI(3,3,new float[]{-1.0f,-2.0f,-1.0f,0.0f,0.0f,0.0f,1.0f,2.0f,1.0f});
  RenderedImage dblImg=FormatDescriptor.create(stripImage,DataBuffer.TYPE_DOUBLE,null);
  RenderedImage sxImg=ConvolveDescriptor.create(dblImg,sxKernel,null);
  RenderedImage syImg=ConvolveDescriptor.create(dblImg,syKernel,null);
  SampleModel sm=sxImg.getSampleModel();
  int nbands=sm.getNumBands();
  double[] sxPixel=new double[nbands];
  double[] syPixel=new double[nbands];
  Rectangle perfArea=new Rectangle(0,0,stripImage.getWidth() / 4,stripImage.getHeight());
  RectIter sxIter=RectIterFactory.create(sxImg,perfArea);
  RectIter syIter=RectIterFactory.create(syImg,perfArea);
  int width=(int)perfArea.getWidth();
  int height=(int)perfArea.getHeight();
  int accumHeight=(int)maxCornerRadius + 2;
  int[][] startAccum=new int[(int)(maxCornerRadius - minCornerRadius)][width * accumHeight];
  int[][] endAccum=new int[(int)(maxCornerRadius - minCornerRadius)][width * accumHeight];
  List<Point> startCorners=new ArrayList<Point>();
  List<Point> endCorners=new ArrayList<Point>();
  int y=0;
  int maxVal=0;
  if (analysisListener != null) {
    analysisListener.scanAnalysisProgress(0,height);
  }
  while (!sxIter.nextLineDone() && !syIter.nextLineDone()) {
    if (y % 1000 == 0 && y > 0) {
      System.out.println("String_Node_Str" + y + "String_Node_Str");
    }
    sxIter.startPixels();
    syIter.startPixels();
    int x=0;
    while (!sxIter.nextPixelDone() && !syIter.nextPixelDone()) {
      sxIter.getPixel(sxPixel);
      syIter.getPixel(syPixel);
      double isq=sxPixel[0] * sxPixel[0] + syPixel[0] * syPixel[0];
      if (isq > EDGE_MIN_GRADIENT * EDGE_MIN_GRADIENT) {
        if (syPixel[0] <= 0 && sxPixel[0] >= 0) {
          double intensity=Math.sqrt(isq);
          for (double r=minCornerRadius; r < maxCornerRadius; r+=1.0) {
            double cx=(double)x - r * sxPixel[0] / intensity;
            double cy=(double)y - r * syPixel[0] / intensity;
            if (cx > 0.0) {
              int accumLine=(int)cy % accumHeight;
              startAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine]++;
              if (startAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine] > maxVal) {
                maxVal=startAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine];
              }
            }
          }
        }
        if (syPixel[0] >= 0 && sxPixel[0] >= 0) {
          double intensity=Math.sqrt(isq);
          for (double r=minCornerRadius; r < maxCornerRadius; r+=1.0) {
            double cx=(double)x - r * sxPixel[0] / intensity;
            double cy=(double)y - r * syPixel[0] / intensity;
            if (cx > 0.0 && cy > 0.0) {
              int accumLine=(int)cy % accumHeight;
              endAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine]++;
              if (endAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine] > maxVal) {
                maxVal=endAccum[(int)(r - minCornerRadius)][(int)cx + width * accumLine];
              }
            }
          }
        }
      }
      x++;
    }
    y++;
    int y2=y - accumHeight;
    int l=y % accumHeight;
    if (y2 > 0) {
      for (int n=0; n < perfArea.getWidth(); n++) {
        for (int r=0; r < (int)(maxCornerRadius - minCornerRadius); r++) {
          if (startAccum[r][n + width * l] >= CORNER_MIN_HOUGH) {
            int val=startAccum[r][n + width * l];
            if (val == getLocalMaxima(startAccum,r,n,y,width)) {
              startCorners.add(new Point(n,y));
              System.out.println(String.format("String_Node_Str",val,r,n,y));
            }
          }
          if (endAccum[r][n + width * l] > CORNER_MIN_HOUGH) {
            int val=endAccum[r][n + width * l];
            if (val == getLocalMaxima(endAccum,r,n,y2,width)) {
              endCorners.add(new Point(n,y2));
              System.out.println(String.format("String_Node_Str",val,r,n,y2));
            }
          }
        }
      }
    }
    for (int n=0; n < perfArea.getWidth(); n++) {
      for (int r=0; r < (int)(maxCornerRadius - minCornerRadius); r++) {
        startAccum[r][n + width * (y % accumHeight)]=0;
        endAccum[r][n + width * (y % accumHeight)]=0;
      }
    }
    if ((y % 100 == 1) && analysisListener != null) {
      analysisListener.scanAnalysisProgress(y - 1,height);
    }
  }
  if (analysisListener != null) {
    analysisListener.scanAnalysisProgress(height,height);
  }
  for (  Point sp : startCorners) {
    for (    Point ep : endCorners) {
      if (ep.y - sp.y > CC_MAX_DIST) {
        break;
      }
      if (Math.abs(ep.x - sp.x) < 10 && ep.y - sp.y > CC_MIN_DIST) {
        Perforation p=new Perforation();
        p.x=(ep.x + sp.x) >> 1;
        p.y=(ep.y + sp.y) >> 1;
        addPointToCluster(p.x,p.y);
      }
    }
  }
  System.out.println(String.format("String_Node_Str",pointClusters.size()));
  for (  PointCluster c : pointClusters) {
    System.out.println(String.format("String_Node_Str",c.getCentroidX(),c.getCentroidY(),c.getPointCount()));
  }
}