目录

一、最小外接矩形

二、最大内接矩形

三、最大内接圆

四、最小外接圆

五、拟合椭圆


一、最小外接矩形

这里的图片是mask,类似于这样的:

绘制如上图片的最小外接矩阵:

def draw_min_rect_rectangle(mask_path):
    image = cv2.imread(mask_path)

    thresh = cv2.Canny(image, 128, 256)

    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    img = np.copy(image)

    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        # 绘制矩形
        cv2.rectangle(img,  (x, y+h), (x+w, y), (0, 255, 255))

绘制结果:

也可以将矩形区域作成新的mask:

    # 将最小内接矩形填充为白色
    white = [255, 255, 255]
    for col in range(x, x+w):
        for row in range(y, y+h):
            image[row, col] = white

那么我们的最小内接矩阵mask就绘制好了:

也可以通过x,y,w,h对图片进行切割:

    pic = cv2.imread(original_img_path) # 读取mask对应的图片
    cut = pic[y:y+h, x:x+w]   # 根据内接矩形的顶点切割图片
    cv2.imwrite(save_path, cut) # 保存切割好的图片

也可以通过最小内接矩形mask来进行切割:

    rectangle_mask_gray = cv2.cvtColor(rectangle_mask, cv2.COLOR_RGB2GRAY) # 此处的image是我们之前获取的最小内接矩形的mask
    pic = cv2.imread(original_img_path)  # 读取mask对应的图像
    out = cv2.bitwise_and(pic, pic, mask=rectangle_mask) # 根据mask切割
    cv2.imshow("min rect rectangle mask cut img", out)

效果如下:

二、最大内接矩形

def maximum_internal_rectangle(mask_path):
    img = cv2.imread(mask_path)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    ret, img_bin = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY)

    contours, _ = cv2.findContours(img_bin, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)

    contour = contours[0].reshape(len(contours[0]), 2)

    rect = []

    for i in range(len(contour)):
        x1, y1 = contour[i]
        for j in range(len(contour)):
            x2, y2 = contour[j]
            area = abs(y2 - y1) * abs(x2 - x1)
            rect.append(((x1, y1), (x2, y2), area))

    all_rect = sorted(rect, key=lambda x: x[2], reverse=True)

    if all_rect:
        best_rect_found = False
        index_rect = 0
        nb_rect = len(all_rect)

        while not best_rect_found and index_rect < nb_rect:

            rect = all_rect[index_rect]
            (x1, y1) = rect[0]
            (x2, y2) = rect[1]

            valid_rect = True

            x = min(x1, x2)
            while x < max(x1, x2) + 1 and valid_rect:
                if any(img[y1, x]) == 0 or any(img[y2, x]) == 0:
                    valid_rect = False
                x += 1

            y = min(y1, y2)
            while y < max(y1, y2) + 1 and valid_rect:
                if any(img[y, x1]) == 0 or any(img[y, x2]) == 0:
                    valid_rect = False
                y += 1

            if valid_rect:
                best_rect_found = True

            index_rect += 1

        if best_rect_found:
            # 如果要在灰度图img_gray上画矩形,请用黑色画(0,0,0)
            cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 1)
            cv2.imshow("rec", img)
            cv2.waitKey(0)

        else:
            print("No rectangle fitting into the area")

    else:
        print("No rectangle found")

三、最大内接圆

先看效果:

再放代码:

# 读取图片,转灰度
mask = cv2.imread(mask_path)
mask_gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)

# 识别轮廓
contours, _ = cv2.findContours(mask_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 计算到轮廓的距离
raw_dist = np.empty(mask_gray.shape, dtype=np.float32)
for i in range(mask_gray.shape[0]):
    for j in range(mask_gray.shape[1]):
        raw_dist[i, j] = cv2.pointPolygonTest(contours[0], (j, i), True)

# 获取最大值即内接圆半径,中心点坐标
minVal, maxVal, _, maxDistPt = cv2.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)

# 画出最大内接圆
result = cv2.cvtColor(mask_gray, cv2.COLOR_GRAY2BGR)
radius = np.int(maxVal)
center_of_circle = maxDistPt
cv2.circle(result, maxDistPt, radius, (0, 255, 0), 2, 1, 0)
cv2.imshow('Maximum inscribed circle', result)
cv2.waitKey(0)

四、最小外接圆

效果:

 代码:

def minimum_external_circle(mask_path):

    img = cv2.imread(mask_path)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    contours, _ = cv2.findContours(img_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

    cnt = contours[0]

    (x, y), radius = cv2.minEnclosingCircle(cnt)
    center = (int(x), int(y))  # 最小内接圆圆心
    radius = int(radius)
    cv2.circle(img, center, radius, (0, 255, 0), 2)
    cv2.circle(img, center, 1, (0, 255, 0), 2)
    cv2.imshow('ret', img)

    cv2.waitKey(0)

五、拟合椭圆

效果:

 代码:

def fit_ellipse(mask_path):
    img = cv2.imread(mask_path)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    contours, _ = cv2.findContours(img_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 拟合椭圆
    ellipse = cv2.fitEllipse(contours[0])

    cv2.ellipse(img, ellipse, (255, 0, 255), 2)
    ellipse_center = (int(ellipse[0][0]), int(ellipse[0][1]))  # 椭圆圆心坐标
    cv2.circle(img, ellipse_center, 1, (255, 0, 255), 2)
    cv2.imshow('ellipse', img)
    cv2.waitKey(0)

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐