如何获得描摹图像的角点?
How to get corners of a traced image?
我正在尝试使用边缘检测来找到扫描纸的 4 个角,以便将其裁剪掉。这是我的代码,但它没有正确检测到这些点。我正在尝试在没有 OpenCV 的情况下执行此操作。
detectEdges(image);
HashMap<Integer, Integer> corners = new HashMap<>();
HashMap<Integer, Integer> reverseCorners = new HashMap<>();
int white = new Color(255, 255, 255).getRGB();
int red = new Color(255, 0, 0).getRGB();
int Blue = new Color(0, 0, 255).getRGB();
for (int i = 2; i < image.getWidth() - 2; i++) {
for (int j = 2; j < image.getHeight() - 2; j++) {
int color = image.getRGB(i, j);
int right = image.getRGB(i + 1, j);
int left = image.getRGB(i - 1, j);
int top = image.getRGB(i, j + 1);
int bottom = image.getRGB(i, j - 1);
int rightCheck = image.getRGB(i + 2, j);
int leftCheck = image.getRGB(i - 2, j);
int topCheck = image.getRGB(i, j + 2);
int bottomCheck = image.getRGB(i, j - 2);
if (color == white) {
//TR Corner
boolean isCornerLR = (((right != white && rightCheck != white) && (left == white && leftCheck == white)) || ((left != white && leftCheck != white) && (right == white && rightCheck == white)));
boolean isCornerTD = (((top != white && topCheck != white) && (bottom == white && bottomCheck == white)) || ((bottom != white && bottomCheck != white) && (top == white && topCheck == white)));
if (isCornerLR && isCornerTD) {
corners.put(i, j);
image.setRGB(i, j, red);
}
}
}
}
HashMap<Integer, Integer> extremeCorners = new HashMap<>();
/*Get opposite corners of shape. so, Bottom left to Top Right, or Top Left to Bottom Right
for case one, (LowKey,LowValue), (HighKey, HighKeyValue). Case two - (LowKey,HighValue),(HighKey,LowValue)
*/
List<Integer> valueOfValue = new ArrayList<>(corners.values());
for (int a : corners.keySet()) {
reverseCorners.put(corners.get(a), a);
}
Collections.sort(valueOfValue);
int yCorner1 = valueOfValue.get(valueOfValue.size() - 1);
int yCorner2 = valueOfValue.get(0);
int xCorner1 = reverseCorners.get(yCorner1);
int xCorner2 = reverseCorners.get(yCorner2);
System.out.println(corners);
extremeCorners.put(xCorner1, yCorner1);
image.setRGB(xCorner1, yCorner1, Blue);
image.setRGB(xCorner2, yCorner2, Blue);
extremeCorners.put(xCorner2, yCorner2);
File f = new File("EdgeImages/" + name);
ImageIO.write(image, "png", f);
return extremeCorners;
}
所以这段代码的作用是寻找潜在的角落并用红色标记它们并将它们添加到哈希图中,这在获取潜在角落方面非常准确。从那里,我尝试制作另一个存储 2 个角的哈希图。这是代码不起作用的地方,我确定这是我的逻辑错误,但我不确定如何从这里继续。
下面附上图片
低精度解决方案:
考虑由轮廓形成的斑点并扫描它的像素(轮廓像素可以做)。对于每个像素,计算 X+Y 和 X-Y 的值,并跟踪产生这些量的最小值和最大值的像素。这是四个角。可能是轮廓被分割成几块,使用所有块的像素就可以了。
高精度解决方案:
用上面的方法,找到角点,粗略画出两条对角线。然后将像素分类为属于由这些对角线定义的象限之一。建议丢弃靠近角落的像素,因为它们的分类不确定。
最后,使用您最喜欢的直线拟合方法,在四个点子集上拟合一条直线。
我正在尝试使用边缘检测来找到扫描纸的 4 个角,以便将其裁剪掉。这是我的代码,但它没有正确检测到这些点。我正在尝试在没有 OpenCV 的情况下执行此操作。
detectEdges(image);
HashMap<Integer, Integer> corners = new HashMap<>();
HashMap<Integer, Integer> reverseCorners = new HashMap<>();
int white = new Color(255, 255, 255).getRGB();
int red = new Color(255, 0, 0).getRGB();
int Blue = new Color(0, 0, 255).getRGB();
for (int i = 2; i < image.getWidth() - 2; i++) {
for (int j = 2; j < image.getHeight() - 2; j++) {
int color = image.getRGB(i, j);
int right = image.getRGB(i + 1, j);
int left = image.getRGB(i - 1, j);
int top = image.getRGB(i, j + 1);
int bottom = image.getRGB(i, j - 1);
int rightCheck = image.getRGB(i + 2, j);
int leftCheck = image.getRGB(i - 2, j);
int topCheck = image.getRGB(i, j + 2);
int bottomCheck = image.getRGB(i, j - 2);
if (color == white) {
//TR Corner
boolean isCornerLR = (((right != white && rightCheck != white) && (left == white && leftCheck == white)) || ((left != white && leftCheck != white) && (right == white && rightCheck == white)));
boolean isCornerTD = (((top != white && topCheck != white) && (bottom == white && bottomCheck == white)) || ((bottom != white && bottomCheck != white) && (top == white && topCheck == white)));
if (isCornerLR && isCornerTD) {
corners.put(i, j);
image.setRGB(i, j, red);
}
}
}
}
HashMap<Integer, Integer> extremeCorners = new HashMap<>();
/*Get opposite corners of shape. so, Bottom left to Top Right, or Top Left to Bottom Right
for case one, (LowKey,LowValue), (HighKey, HighKeyValue). Case two - (LowKey,HighValue),(HighKey,LowValue)
*/
List<Integer> valueOfValue = new ArrayList<>(corners.values());
for (int a : corners.keySet()) {
reverseCorners.put(corners.get(a), a);
}
Collections.sort(valueOfValue);
int yCorner1 = valueOfValue.get(valueOfValue.size() - 1);
int yCorner2 = valueOfValue.get(0);
int xCorner1 = reverseCorners.get(yCorner1);
int xCorner2 = reverseCorners.get(yCorner2);
System.out.println(corners);
extremeCorners.put(xCorner1, yCorner1);
image.setRGB(xCorner1, yCorner1, Blue);
image.setRGB(xCorner2, yCorner2, Blue);
extremeCorners.put(xCorner2, yCorner2);
File f = new File("EdgeImages/" + name);
ImageIO.write(image, "png", f);
return extremeCorners;
}
所以这段代码的作用是寻找潜在的角落并用红色标记它们并将它们添加到哈希图中,这在获取潜在角落方面非常准确。从那里,我尝试制作另一个存储 2 个角的哈希图。这是代码不起作用的地方,我确定这是我的逻辑错误,但我不确定如何从这里继续。
下面附上图片
低精度解决方案:
考虑由轮廓形成的斑点并扫描它的像素(轮廓像素可以做)。对于每个像素,计算 X+Y 和 X-Y 的值,并跟踪产生这些量的最小值和最大值的像素。这是四个角。可能是轮廓被分割成几块,使用所有块的像素就可以了。
高精度解决方案:
用上面的方法,找到角点,粗略画出两条对角线。然后将像素分类为属于由这些对角线定义的象限之一。建议丢弃靠近角落的像素,因为它们的分类不确定。
最后,使用您最喜欢的直线拟合方法,在四个点子集上拟合一条直线。