4
社区成员
发帖
与我相关
我的任务
分享
import cv2 as cv
import numpy as np
class ContourProcessing:
def __init__(self, image_path):
self.image_path = image_path
self.img = cv.imread(self.image_path)
if self.img is None:
raise FileNotFoundError(f"无法读取图像文件: {self.image_path}")
self.imgray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)
def draw_contours(self):
"""
绘制图像的轮廓
"""
ret, thresh = cv.threshold(self.imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# 绘制所有轮廓
cv.drawContours(self.img, contours, -1, (0, 255, 0), 3)
# 绘制索引为3的轮廓
cv.drawContours(self.img, contours, 3, (0, 255, 0), 3)
# 绘制索引为4的轮廓
cnt = contours[4]
cv.drawContours(self.img, [cnt], 0, (0, 255, 0), 3)
cv.imshow('Contours', self.img)
cv.waitKey(0)
cv.destroyAllWindows()
def contour_features(self):
"""
计算并显示轮廓的特征
"""
img_gray = cv.imread(self.image_path, 0)
ret, thresh = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
# 特征矩
M = cv.moments(cnt)
if M['m00'] != 0:
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
else:
cx, cy = 0, 0
# 轮廓面积
area = cv.contourArea(cnt)
# 轮廓周长
perimeter = cv.arcLength(cnt, True)
# 轮廓近似
epsilon = 0.1 * cv.arcLength(cnt, True)
approx = cv.approxPolyDP(cnt, epsilon, True)
# 轮廓凸包
hull = cv.convexHull(cnt)
# 检查凸度
k = cv.isContourConvex(cnt)
# 边界矩形(直角矩形)
x, y, w, h = cv.boundingRect(cnt)
cv.rectangle(img_gray, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 最小闭合圈
(x, y), radius = cv.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
cv.circle(img_gray, center, radius, (0, 255, 0), 2)
# 拟合一个椭圆
ellipse = cv.fitEllipse(cnt)
cv.ellipse(img_gray, ellipse, (0, 255, 0), 2)
print(f"质心: ({cx}, {cy})")
print(f"轮廓面积: {area}")
print(f"轮廓周长: {perimeter}")
print(f"轮廓近似: {approx}")
print(f"轮廓凸包: {hull}")
print(f"凸度: {k}")
cv.imshow('Contour Features', img_gray)
cv.waitKey(0)
cv.destroyAllWindows()
def contour_properties(self):
"""
计算并显示轮廓的属性
"""
img_gray = cv.imread(self.image_path, 0)
ret, thresh = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
# 长宽比
x, y, w, h = cv.boundingRect(cnt)
if h != 0:
aspect_ratio = float(w) / h
else:
aspect_ratio = 0
# 范围
area = cv.contourArea(cnt)
rect_area = w * h
if rect_area != 0:
extent = float(area) / rect_area
else:
extent = 0
# 坚实度
hull = cv.convexHull(cnt)
hull_area = cv.contourArea(hull)
if hull_area != 0:
solidity = float(area) / hull_area
else:
solidity = 0
# 等效直径
if area != 0:
equi_diameter = np.sqrt(4 * area / np.pi)
else:
equi_diameter = 0
# 取向
(x, y), (MA, ma), angle = cv.fitEllipse(cnt)
# 极端点
leftmost = tuple(cnt[cnt[:, :, 0].argmin()][0])
rightmost = tuple(cnt[cnt[:, :, 0].argmax()][0])
topmost = tuple(cnt[cnt[:, :, 1].argmin()][0])
bottommost = tuple(cnt[cnt[:, :, 1].argmax()][0])
print(f"长宽比: {aspect_ratio}")
print(f"范围: {extent}")
print(f"坚实度: {solidity}")
print(f"等效直径: {equi_diameter}")
print(f"取向: 中心({x}, {y}), 长轴 {MA}, 短轴 {ma}, 角度 {angle}")
print(f"极端点: 最左 {leftmost}, 最右 {rightmost}, 最上 {topmost}, 最下 {bottommost}")
def convexity_defects(self):
"""
检测并显示轮廓的凸性缺陷
"""
img = cv.imread(self.image_path)
img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, thresh = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, 2, 1)
cnt = contours[0]
hull = cv.convexHull(cnt, returnPoints=False)
defects = cv.convexityDefects(cnt, hull)
if defects is not None:
for i in range(defects.shape[0]):
s, e, f, d = defects[i, 0]
start = tuple(cnt[s][0])
end = tuple(cnt[e][0])
far = tuple(cnt[f][0])
cv.line(img, start, end, [0, 255, 0], 2)
cv.circle(img, far, 5, [0, 0, 255], -1)
cv.imshow('Convexity Defects', img)
cv.waitKey(0)
cv.destroyAllWindows()
def point_polygon_test(self, point=(50, 50)):
"""
进行点多边形测试
"""
img_gray = cv.imread(self.image_path, 0)
ret, thresh = cv.threshold(img_gray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, 1, 2)
cnt = contours[0]
dist = cv.pointPolygonTest(cnt, point, True)
print(f"点 {point} 到多边形的距离: {dist}")
def shape_matching(self, other_image_path):
"""
进行形状匹配
"""
img1 = cv.imread(self.image_path, 0)
img2 = cv.imread(other_image_path, 0)
if img1 is None or img2 is None:
raise FileNotFoundError("无法读取图像文件")
ret, thresh = cv.threshold(img1, 127, 255, 0)
ret, thresh2 = cv.threshold(img2, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, 2, 1)
cnt1 = contours[0]
contours, hierarchy = cv.findContours(thresh2, 2, 1)
cnt2 = contours[0]
ret = cv.matchShapes(cnt1, cnt2, 1, 0.0)
print(f"形状匹配结果: {ret}")