本文主要是介绍判断单张图片是否存在重叠部分的常见方法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Python-判断单张图片中是否存在重叠部分的常见方法通常包括以下几种:
- 使用边缘检测和轮廓发现
像上面提到的那样,你可以使用OpenCV库中的边缘检测(如Canny算法)和轮廓发现函数findContours,利用轮廓层级关系来判断是否有重叠。 - 特征匹配
这适用于需要检测图像中相似对象重叠的情况。可以通过SIFT、SURF或ORB等特征点检测和描述算子兼已知模式匹配的方法来识别重叠部分。 - 模板匹配
对于已知模板的情况,可以使用OpenCV的模板匹配函数matchTemplate。如果模板在图像中匹配多个位置,则可以推断这些区域与模板重叠。 - 根据像素值分析
分析图像中每个像素与其邻居之间的关系,由此可以检测重叠的纹理或图案。(例如:使用局部二值模式Local Binary Patterns (LBPs)) - 机器学习和深度学习
创建一个定制的模型来学习识别重叠部分的特征。例如,使用基于卷积神经网络(CNN)的深度学习模型,可以在图像中识别和定位重叠部分
用边缘检测和轮廓查找来实现的简单示例
import cv2
def find_buff_1():# 加载图片image = cv2.imread('1.png')# 转换图片为灰度图gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 应用阈值化,以便更容易找到轮廓_, thresh = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY_INV)# 找到轮廓contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# 遍历轮廓,检查层级关系overlap = Falseif hierarchy is None:print("没有找到轮廓")else:# hierarchy结构:[Next, Previous, First_Child, Parent]# 当轮廓具有Parent时(hierarchy[0, i, 3] != -1),它可能是重叠的for i in range(len(contours)):if hierarchy[0, i, 3] != -1:overlap = True# 这里简单地输出重叠轮廓cv2.drawContours(image, contours, i, (0, 255, 0), 3)breakif overlap:print("存在重叠的部分")cv2.imshow("Overlaps", image)cv2.waitKey(0)cv2.destroyAllWindows()else:print("不存在重叠的部分")
SIFT、SURF和ORB是用于特征点检测和描述的三种不同算法,它们可以用来在图像中找到关键点,并且为这些关键点生成一个描述符(descriptor)来捕获其周围区域的唯一性。这些算法特别适用于图像匹配、对象识别、立体视觉和导航等问题,因为它们对图像旋转、尺度变换、亮度变化等有一定的不变性(即使图像的角度或大小不同,也能识别出相同的特征点)。
下面分别介绍这三种技术:
SIFT(尺度不变特征变换)
SIFT算法由David Lowe在1999年首次提出,并在2004年完善。SIFT用于检测和描述图像中的局部特征点,并具有很高的尺度和旋转不变性。SIFT的关键步骤包括:
尺度空间极值检测:搜索所有尺度上的图像位置。通过高斯微分函数来识别潜在的具有不变性的关键点。
关键点定位:在每个候选的位置上精确定位关键点。
方向确定:基于局部图像梯度的方向,给每个关键点分配一个或多个方向。
关键点描述:在每个关键点周围的区域内测量图像的局部梯度直方图,并转化为描述符。
SURF(加速鲁棒特征)
SURF算法由Bay等人在2006年提出,被认为是SIFT的加速版本。它在很多方面与SIFT相似,但利用了近似或者整数的特征点检测方法从而加速计算过程。SURF侧重于速度和性能,并能在计算描述子时保持较高的尺度和旋转不变性。
ORB(Oriented FAST and Rotated BRIEF)
ORB算法由Rublee等人于2011年提出,是一种非常高效的特征点检测和描述算法。ORB基于FAST关键点检测器和BRIEF描述符,它进行了一些改进,以提高匹配的稳定性和对旋转的不变性。ORB首先使用FAST来查找关键点,然后用哈里斯角点测度对这些关键点进行排序以找到顶部N个点。使用图像的中心矩(intensity weighted centroid)来指定方向,然后它采用一个角度相对于方向旋转的BRIEF描述符。
由于SIFT和SURF是受专利保护的算法,所以在商业应用中可能需要获得许可才能使用。而ORB是一种免费的算法,对于需要免费且效果较好的特征检测与匹配方法而言,ORB是一个很好的选择。
这些算法可以使用OpenCV库在Python中轻松实现,以下是ORB算法的一个使用示例:
import cv2
import numpy as np# 读取图像
img = cv2.imread('path_to_image.jpg', 0)
# 初始化ORB检测器
orb = cv2.ORB_create()
# 检测关键点
keypoints = orb.detect(img, None)
# 计算描述子
keypoints, descriptors = orb.compute(img, keypoints)
# 可视化关键点
out_img = np.zeros_like(img)
out_img = cv2.drawKeypoints(img, keypoints, out_img, color=(255,0,0))
# 显示图像
cv2.imshow('ORB keypoints', out_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
OpenCV库提供了模板匹配函数 cv2.matchTemplate(),它是一个简单而有效的方法来在更大的图像中搜索和找到模板图像的位置。模板匹配通过在原始图像中滑动模板图像以作为子图像,并在每一个位置上比较子图像与模板的相似度,来工作。
这种方法对于寻找不同尺度或旋转的模板可能不是很有效,因为 matchTemplate 仅仅检查位置的匹配,但对于没有旋转和尺度变化的图像来说,它是一个非常直接的解决方案。
OpenCV提供了几种不同的比较方法,如 cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED, cv2.TM_CCORR, cv2.TM_CCORR_NORMED, cv2.TM_SQDIFF, 和 cv2.TM_SQDIFF_NORMED。通常 cv2.TM_CCOEFF_NORMED 和 cv2.TM_CCORR_NORMED 提供归一化的分数,便于解释。
import cv2
import numpy as np# 读取原始图像和模板图像
img = cv2.imread('path_to_image.jpg')
template = cv2.imread('path_to_template.jpg')
h, w = template.shape[:2]
# 执行模板匹配操作
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
# 设定阈值和匹配方法
threshold = 0.8
# 仅挑选匹配程度高于阈值的点
loc = np.where(res >= threshold)
# 用矩形标注匹配到的区域
for pt in zip(*loc[::-1]): # Switch collumns and rowscv2.rectangle(img, pt, (pt[0] + w, pt[1] + h), (0,255,0), 2)
# 显示绘制了矩形标注的原始图像
cv2.imshow('Detected', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
在上面的代码中,首先读取原始图像和模板图像文件,然后使用 matchTemplate 函数找到模板在原始图像中的所有匹配区域。之后,基于特定的阈值,通过 np.where 函数找到匹配度较高的点的坐标。每个点的坐标代表模板图像左上角在原始图像中的位置。然后,使用 cv2.rectangle 函数画出矩形标注,标识出匹配到的区域。
通常,如果在图像中找到了多个匹配区域,可能表明图像中存在多个相似或相同的模板,这有时候也可以理解为一种重叠,尤其是当模板小于或接近待检测的物体大小时。不过,要注意 matchTemplate 不是专门设计来检测重叠的方法。如果需要处理旋转或尺度变化,可能需要考虑更复杂的特征点匹配算法
局部二值模式(Local Binary Patterns,简称LBPs)是一种简单而有效的纹理描述子。它在各种条件下表现出了良好的稳定性和鲁棒性,特别适用于纹理分类。LBPs可以提取图像局部区域内的纹理信息,通过比较每个像素与其周围邻居的强度来生成一个二进制数。
基本的LBP算子定义如下:
选取图像中的一个像素作为中心像素。
将中心像素的邻域(通常是3x3、5x5等)的每个像素的强度值与中心像素的值进行比较。
如果周围的像素值大于中心像素值,则该位置记为1,否则记为0。
这样会得到每个像素的一个二进制数(二进制模式),将这个二进制数转换为十进制作为该中心像素的新值。
对图像中的所有像素重复上述过程,最后得到的新图像就是LBP特征图。
LBP特征图可以用于纹理识别,也可以用于查找图像中的重复模式或纹理,在某些情况下可能隐含着重叠区域。
注意,直接使用LBP可能不能确定图像中是否存在重叠部分。为了使用LBP分析重叠,您可能需要结合其他图像处理步骤,例如分割图像中可能重叠的区域,然后在这些区域使用LBP来比较它们的纹理模式。如果两个区域具有高度相似的LBPs,则它们可能包含重叠的纹理。
import cv2
import numpy as np
from skimage import feature# 读取灰度图像
image = cv2.imread('path_to_image.jpg', cv2.IMREAD_GRAYSCALE)# 使用skimage库中的LBP函数
radius = 1 # LBP中用到的圆的半径
n_points = 8 * radius # 采样点的数量
lbp = feature.local_binary_pattern(image, n_points, radius, method="uniform")
# 现在,lbp变量包含了图像的LBP特征图
# 你可以做更多的处理,比如计算LBP图像的直方图:
lbp_hist, _ = np.histogram(lbp, bins=np.arange(257), range=(0, 256))
lbp_hist = lbp_hist.astype("float")
lbp_hist /= (lbp_hist.sum() + 1e-7) # 归一化直方图
# 这个直方图现在可以用于纹理分类或被用作特征向量进一步的图像分析。
# 可视化LBP图像
cv2.imshow('LBP Image', lbp.astype('float32'))
cv2.waitKey(0)
cv2.destroyAllWindows()
这里,使用feature.local_binary_pattern函数从skimage库中计算LBP图,然后计算它的直方图。这个直方图可以作为一种特征向量在图像间比较纹理。
要使用这个直方图进行重叠检测,你可以比较多个区域的LBP直方图,并根据相似度来判断是否存在重叠。这通常需要额外的逻辑来定义何种程度的相似度阈值被认为是重叠.
这篇关于判断单张图片是否存在重叠部分的常见方法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!