如何判断两个像素是不是属于同一行

Posted

技术标签:

【中文标题】如何判断两个像素是不是属于同一行【英文标题】:How to determine if two pixels belong to the same line如何判断两个像素是否属于同一行 【发布时间】:2021-04-11 11:35:01 【问题描述】:

我在黑色背景上有两条白线。我需要输入两个白色像素的坐标并得到这些像素是否属于同一行的答案。线条为 1 像素宽。

【问题讨论】:

我认为你需要先进行对象分割,区分两条线,然后进行检查。 你可以很容易地用霍夫变换做到这一点。 从任一白色像素开始,用黑色填充。检查其他起始像素的颜色。如果它仍然是白色的,它就不能在我们刚刚填充黑色的同一条线上。如果线条交叉,算法会失败???? 用白线连接两个白色像素。现在检查你有多少对象。如果为 1,则这些点必须位于不同的线上,并由我们构建的新线连接。如果为 2,则新行位于两条原始行之一的顶部,因此白色像素位于同一行。 @MarkSetchell 在显示的图像中,许多像素仅在对角线上接触,而不是水平/垂直接触。 Floodfill 通常不适用于对角线。 【参考方案1】:

考虑到这个问题的约束,你可以只遍历两个白色像素之间的路径,求和该路径之间有多少白色像素。如果它们在同一条线上,你会加起来很多,否则,大部分路径都会在黑色上。此外,您应该通过路径长度对总和进行归一化,并将结果与​​给定的阈值进行比较。

//x1, y1, x2, y2 and img given as input
double len = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2) + 0.0001;
double dx = (x2-x1)/len; // Division by zero safe
double dy = (y2-y1)/len;
int sum = 0;
for (int i=0; i<len; ++i) 
    int x = x1 + (dx*i + 0.5); // 0.5 for rounding when truncating
    int y = y1 + (dy*i + 0.5);
    sum += img.at<uchar>(y,x) > 200; // White value higher than 200

if (sum > len * 0.5)  // 0.5 is the threshold
    return 1; // They are on the same line

return 0; // Else they are on different lines

注意我选择为 0.5 的舍入参数,这取决于您如何生成这些线。

【讨论】:

【参考方案2】:

这就是我在 cmets 中的建议......从白色像素开始,用黑色填充。检查其他起始像素的颜色。如果它仍然是白色的,它就不能在我们刚刚填充黑色的同一行上。

import cv2

# Load image as greyscale
im = cv2.imread('lines.png', cv2.IMREAD_GRAYSCALE)

w1x, w1y = 171, 108     # bottom line, right end
w2x, w2y = 86, 124      # bottom line. left end
w3x, w3y = 44, 74       # top line, left end
w4x, w4y = 143,25       # top line, right end

# Floodfill with black starting at white px 1
cv2.floodFill(im, None, (w1x,w1y), newVal=0, loDiff=50, upDiff=50, flags=8)
    
# Check white px 2
print(im[w2y, w2x])      # prints 0 because white px 2 is on same line as white px 1

# Check white px 3
print(im[w3y, w3x])      # prints 255, because white px 3 is on other line 

# Check white px 4
print(im[w4y, w4x])      # prints 255, because white px 4 is on other line 


这是我在 cmets 中建议的另一种方法...用白线连接两个点,看看图像中现在有多少对象。如果还有 2 个,我们沿着其中一条线绘制。如果现在有 1 个对象,那么我们构造的线必须将其他两个对象连接在一起成为一个更大的对象:

import cv2
im = cv2.imread('lines.png', cv2.IMREAD_GRAYSCALE)

# Count objects - initially 2
nObjects = len(cv2.findContours(im, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0])

# Draw white line connecting white px 1 and white px 2
cv2.line(im,(w1x,w1y),(w2x,w2y),255,1)

# Count objects - still 2
nObjects = len(cv2.findContours(im, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0])

# Draw white line connecting white px 1 and white px 3
cv2.line(im,(w1x,w1y),(w3x,w3y),255,1)

# Count objects - now just 1
nObjects = len(cv2.findContours(im, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0])

【讨论】:

以上是关于如何判断两个像素是不是属于同一行的主要内容,如果未能解决你的问题,请参考以下文章

如何在同一行获得两个日期选择器?

如何在本机反应中将两个按钮放在同一行中?

Java中怎样判断一个变量是不是属于哪种类型

判断两个IP地址是不是属于同一子网的方法

如何在同一行中编写两个方法[重复]

VB 如何判断两个图片框中的图像是相同或相似