我一直在使用hough变换的Rosetta Code Java implementation,它也很好地生成了累加器的可视化。
给定这样的输入图像:
java - 在原始图像中显示使用Rosetta Code Hough变换找到的行-LMLPHP
累加器如下所示:
java - 在原始图像中显示使用Rosetta Code Hough变换找到的行-LMLPHP
假设我按如下方式编译并调用类:

$ javac HoughTransform.java && java HoughTransform pentagram.png out.png 640 480 100

这是有道理的。现在我想用我找到的线覆盖原始图像,但这给我带来了严重的麻烦。
我只能找到一个例子来做我想用C++写的东西:
...
int x1, y1, x2, y2;
x1 = y1 = x2 = y2 = 0;

if(t >= 45 && t <= 135)
{
  //y = (r - x cos(t)) / sin(t)
  x1 = 0;
  y1 = ((double)(r-(_accu_h/2)) - ((x1 - (_img_w/2) ) * cos(t * DEG2RAD))) / sin(t * DEG2RAD) + (_img_h / 2);
  x2 = _img_w - 0;
  y2 = ((double)(r-(_accu_h/2)) - ((x2 - (_img_w/2) ) * cos(t * DEG2RAD))) / sin(t * DEG2RAD) + (_img_h / 2);
}
else
{
  //x = (r - y sin(t)) / cos(t);
  y1 = 0;
  x1 = ((double)(r-(_accu_h/2)) - ((y1 - (_img_h/2) ) * sin(t * DEG2RAD))) / cos(t * DEG2RAD) + (_img_w / 2);
  y2 = _img_h - 0;
  x2 = ((double)(r-(_accu_h/2)) - ((y2 - (_img_h/2) ) * sin(t * DEG2RAD))) / cos(t * DEG2RAD) + (_img_w / 2);
}
...

https://github.com/brunokeymolen/hough/blob/master/hough.cpp#L125
我试着修改代码,至少看看我是否能得到一般的想法,但是C++版本和RoSeTA代码版本的实现似乎有所不同。
我实现了:
public static void getLines(String filename, int thetaAxisSize, ArrayData arrayData)  throws IOException
{
  BufferedImage inputImage = ImageIO.read(new File(filename));

  double[] sinTable = new double[thetaAxisSize];
  double[] cosTable = new double[thetaAxisSize];
  for (int theta = thetaAxisSize - 1; theta >= 0; theta--)
  {
    double thetaRadians = theta * Math.PI / thetaAxisSize;
    sinTable[theta] = Math.sin(thetaRadians);
    cosTable[theta] = Math.cos(thetaRadians);
  }


  java.awt.Color color = new java.awt.Color(255, 0, 0);

  int max = arrayData.getMax();
  System.out.println("Max value: " + max);

  for (int r = 0; r < arrayData.height; r++)
  {
    for (int theta = 0; theta < arrayData.width; theta++)
    {
      int val = arrayData.get(theta, r);

      if (val < max - 1) {
        continue;
      }

      System.out.println("Found val: " + val + ", r: " + r + ", theta: " + theta);

      int x = (int)(r * cosTable[theta]);
      int y = (int)(r * sinTable[theta]);

      System.out.println("Found val: " + val + ", r: " + r + ", theta: " + theta + ", x/y: " + x + "/" + y);
    }
  }

  ImageIO.write(inputImage, "PNG", new File("/tmp/hough-overlay.png"));
}

但后来被卡住了,结果对我来说已经毫无意义了:
Max value: 217 (this one still makes sense)
Found val: 216, r: 275, theta: 342
Found val: 216, r: 275, theta: 342, x/y: -29/273
Found val: 216, r: 276, theta: 340
Found val: 216, r: 276, theta: 340, x/y: -27/274
Found val: 217, r: 277, theta: 337
Found val: 217, r: 277, theta: 337, x/y: -23/276
Found val: 217, r: 277, theta: 339
Found val: 217, r: 277, theta: 339, x/y: -25/275
Found val: 217, r: 278, theta: 336
Found val: 217, r: 278, theta: 336, x/y: -21/277
Found val: 216, r: 279, theta: 334
Found val: 216, r: 279, theta: 334, x/y: -19/278

我的数学还不足以找出如何将rtheta转换回图像空间,只要找到一条线。我读了很多关于霍夫变换的白皮书和文章,我还是不明白。我发现的几个实现,比如C++版本,似乎都与我拥有的Java版本有点不同。
所以我想知道,有没有人用rosetta代码java实现了hough变换,并成功地将线从极坐标空间转换回原始图像?

最佳答案

你有参数rho,theta的“法”线方程,想要得到两个点定义同一条线

 x *  Cos(Theta) + y * sin(Theta) - Rho = 0

特殊情况:检查Rho=0或θ是否为90*K(水平或垂直)。
Rho = 0-通过坐标原点的直线所以第一点是(0,0)。如果θ=0,取(0, 1)作为第二点,否则取(1, Cotangent(Theta))
如果θ=0或180(垂直)-只需使垂直线X=Rho(例如,点(Rho, 0) and (Rho,1)
如果θ=90/270(水平)-只需使水平线Y=Rho(例如,点(0, Rho) and (1, Rho)
否则-让我们选择与坐标轴的交点作为基线点。代入方程中的x=0和y=0,得到坐标:
 0 *  Cos(Theta) + y * sin(Theta) - Rho = 0
 y = Rho / Sin(Theta)

 x *  Cos(Theta) + 0 * sin(Theta) - Rho = 0
 x = Rho / Cos(Theta)

所以点是(0, Rho / Sin(Theta))(Rho / Cos(Theta), 0)
快速检查Theta = 45, Rho = 0.7071
(0, 1)(1, 0)-好

关于java - 在原始图像中显示使用Rosetta Code Hough变换找到的行,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40600791/

10-09 06:19