cv2函数实践-图像处理(求点到直线距离/旋转框处理/旋转抠图/直线拟合及后处理/求直线交点/轮廓处理)

目录

快速求N个点到一条直线的距离

cv2.minAreaRect函数及旋转框后处理方法

求旋转框的长边、短边、旋转角度、关键点坐标

裁剪旋转框(最小旋正角度抠图)

cv2.fitLine函数及后处理方法

穿过图像画直线

计算两条直线交点

提取图像内部的轮廓点


快速求N个点到一条直线的距离

Python, OpenCV, Numpy

def get_distance_line_and_p_batch(line, p1_list):
    """
    求点到直线距离
    :param line: array([[vx], [vy], [x0], [y0]], dtype=float32)
    :param p1_list: 线外点
    :return:
        每个线外点到直线距离(垂直)
        每个线外点在直线垂线交点的X
        每个线外点在直线垂线交点的Y
    """
    vx, vy, x0, y0 = line
    vx = vx[0]
    vy = vy[0]
    x0 = x0[0]
    y0 = y0[0]

    B0 = [vy * x0 - vx * y0] * len(p1_list)
    B1 = [vx * p1[0] + vy * p1[1] for p1 in p1_list]

    A = np.array([[vy, -vx], [vx, vy]], dtype=np.float32)
    B = np.array([B0, B1], dtype=np.float32)
    ret, X = cv2.solve(A, B, flags=cv2.DECOMP_LU)
    x2 = X[0, :]
    y2 = X[1, :]

    x1 = np.array([p1[0] for p1 in p1_list], dtype=np.float32)
    y1 = np.array([p1[1] for p1 in p1_list], dtype=np.float32)

    return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5, x2, y2

cv2.minAreaRect函数及旋转框后处理方法

求旋转框的长边、短边、旋转角度、关键点坐标
def find_rotRect_long_side(rotRect):
    (cx, cy), (cw, ch), angle = rotRect
    cw2d, ch2d, theta = cw / 2, ch / 2, np.pi * angle / 180  # cw/2, ch/2, 旋转角(弧度制)
    cA = (cx - cw2d * np.cos(theta), cy - cw2d * np.sin(theta))
    cB = (cx + cw2d * np.cos(theta), cy + cw2d * np.sin(theta))
    cC = (cx - ch2d * np.sin(theta), cy + ch2d * np.cos(theta))
    cD = (cx + ch2d * np.sin(theta), cy - ch2d * np.cos(theta))
    # cAB = np.sqrt((cA[0] - cB[0]) ** 2 + (cA[1] - cB[1]) ** 2)  # ==cw
    # cCD = np.sqrt((cC[0] - cD[0]) ** 2 + (cC[1] - cD[1]) ** 2)  # ==ch
    point_AD = (cA[0] + ch2d * np.sin(theta), cA[1] - ch2d * np.cos(theta))  # A和D的所在直线的交点,旋转框的一个角点坐标
    point_AC = (cA[0] - ch2d * np.sin(theta), cA[1] + ch2d * np.cos(theta))
    point_BD = (cB[0] + ch2d * np.sin(theta), cB[1] - ch2d * np.cos(theta))
    point_BC = (cB[0] - ch2d * np.sin(theta), cB[1] + ch2d * np.cos(theta))
    if cw > ch:  # cAB > cCD, cw > ch
        point_start = cA
        point_end = cB
        long_length = float(cw)
        long_angle = angle
        point_upper_long_line = cD
        point_lower_long_line = cC  # cC在cD左下方
        short_length = float(ch)
    else:
        point_start = cC
        point_end = cD
        long_length = float(ch)
        long_angle = angle - 90  # 逆时针
        point_upper_long_line = cA
        point_lower_long_line = cB
        short_length = float(cw)
    # point_start/point_end: 长边方向的起始点和结束点,起始点总是在结束点的左侧
    # point_upper_long_line/point_lower_long_line: 短边方向的两个点,被长边直线隔开
    return dict(point_start=point_start, point_end=point_end, point_center=(cx, cy),
                long_length=long_length, long_angle=long_angle, short_length=short_length,
                point_upper_long_line=point_upper_long_line, point_lower_long_line=point_lower_long_line,
                point_AD=point_AD, point_AC=point_AC, point_BD=point_BD, point_BC=point_BC)
裁剪旋转框(最小旋正角度抠图)
def crop_minAreaRect_with_min_angle(rot3: Tuple, img: np.ndarray):
    (cx, cy), (cw, ch), angle = rot3  # angle属于(0,90],为x轴(矩形最低点) 顺时针 旋转的角度
    height, width = img.shape[:2]
    # min_angle = angle if angle < 45 else angle - 90  # min_angle为正,则逆时针旋转图像
    if angle < 45:
        w, h = cw, ch  # 逆时针旋转跟x轴重合
        rotate_matrix = cv2.getRotationMatrix2D(center=(cx, cy), angle=angle, scale=1)
    else:
        w, h = ch, cw  # 顺时针旋转跟x轴重合
        rotate_matrix = cv2.getRotationMatrix2D(center=(cx, cy), angle=angle - 90, scale=1)
    rotated_image = cv2.warpAffine(src=img, M=rotate_matrix, dsize=(width, height))
    x0, y0 = max(0, int(cx - w/2 + 0.5)), max(0, int(cy - h/2 + 0.5))  # 左上角xy,注意左上角可能越界
    x1, y1 = min(width, int(cx + w/2 + 0.5)), min(height, int(cy + h/2 + 0.5))  # 右下角xy
    return rotated_image[y0:y1, x0:x1]

cv2.fitLine函数及后处理方法

穿过图像画直线
def draw_line_crossImg(img: np.ndarray, line, scale_xy=1.0, color=(0,0,0)):
    """
    穿过整张图,画一条直线
    :param line: fitLine的结果,array([[vx], [vy], [x0], [y0]], dtype=float32)
    :param scale_xy: x0, y0的缩放比例
    """
    h, w = img.shape[:2]
    vx, vy, x0, y0 = line
    vx = vx[0]
    vy = vy[0]
    x0 = x0[0] * scale_xy
    y0 = y0[0] * scale_xy
    pts = []
    dxy = vx / (vy + 1e-7)
    for y1 in [0, h-1]:
        x1 = x0 + (y1 - y0) * dxy
        if 0 <= x1 < w: pts.append((x1, y1))
    if len(pts) < 2:
        dyx = vy / (vx + 1e-7)
        for x1 in [0, w-1]:
            y1 = y0 + (x1 - x0) * dyx
            if 0 <= y1 < h: pts.append((x1, y1))
    cv2.line(img, (round(pts[0][0]), round(pts[0][1])), (round(pts[1][0]), round(pts[1][1])), color)
    return pts

 

计算两条直线交点
def calc_2lines_intersection(line1_params, line2_params):
    """
    计算两直线交点,传入cv2.fitLine返回值格式的两条直线
    Args:
        line1_params:
        line2_params:
    # # 使用cv2.fitLine函数计算两条直线的参数
    # line1_params = cv2.fitLine(np.array([line1_start, line1_end]), cv2.DIST_L2, 0, 0.01, 0.01)
    # line2_params = cv2.fitLine(np.array([line2_start, line2_end]), cv2.DIST_L2, 0, 0.01, 0.01)
    Returns:
    """
    vx, vy, x0, y0 = line1_params
    a1, b1, c1 = vy[0], -vx[0], vx[0] * y0[0] - vy[0] * x0[0]

    vx, vy, x0, y0 = line2_params
    a2, b2, c2 = vy[0], -vx[0], vx[0] * y0[0] - vy[0] * x0[0]

    # 处理平行和垂直的特殊情况
    delta = a2 * b1 - a1 * b2
    if abs(delta) < 1e-10:
        # 平行情况,返回None
        return None
    # 计算交点的x和y坐标
    x_intersect = (b2 * c1 - b1 * c2) / delta
    y_intersect = (a1 * c2 - a2 * c1) / delta
    return x_intersect, y_intersect

提取图像内部的轮廓点

def extract_inside_pts_of_contour(contour, w, h, ):
    """
    contour是在wxh大小的图中的一个轮廓,目的是提取内部轮廓点(剔除图边界上的轮廓点)
    """
    cond_w = (2 < contour[:, 0, 0]) & (contour[:, 0, 0] < w - 2)
    cond_h = (2 < contour[:, 0, 1]) & (contour[:, 0, 1] < h - 2)
    # print(cond_w.shape, cond_h.shape, )  # (163,) (163,)
    return contour[cond_w & cond_h]  # 剔除边界上的轮廓点, (159, 1, 2)

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 以下是Python的代码示例,包含图像二值化、形态学处理轮廓提取、图像抠图并更换背景并进行高斯模糊的过程: ``` import cv2 # 读取原始图像 image = cv2.imread('image.jpg') # 转换为灰度图像 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 图像二值化 ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 形态学处理 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) # 轮廓提取 contours, hierarchy = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 查找主体轮廓 main_contour = max(contours, key=cv2.contourArea) # 绘制主体轮廓 contour_image = cv2.drawContours(image.copy(), [main_contour], -1, (0, 255, 0), 2) # 图像抠图并更换背景 mask = cv2.drawContours(np.zeros_like(gray), [main_contour], 0, 255, -1) background = cv2.imread('background.jpg') background = cv2.resize(background, image.shape[:2][::-1]) background_mask = cv2.bitwise_not(mask) foreground = cv2.bitwise_and(image, image, mask=mask) background = cv2.bitwise_and(background, background, mask=background_mask) result = cv2.add(foreground, background) # 高斯模糊 result = cv2.GaussianBlur(result, (11, 11), 0) # 显示结果图像 cv2.imshow('Result', result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 以上代码中,image为原始图像,background为新背景图像,分别调用cv2.imread进行读取。接下来依次进行图像二值化、形态学处理轮廓提取,通过查找主体轮廓,得到二值化后的主体部分,然后通过对主体部分进行图像抠图操作,并将其与新背景图像进行合并,得到抠出来的主体带新背景的图像。最后进行高斯模糊。注:该代码适用于单一主体的图像。 ### 回答2: 下面是实现图像二值化、形态学处理轮廓提取、抠图、更换背景并进行高斯模糊的Python代码: ```python import cv2 import numpy as np # 读取图像 image = cv2.imread("image.png") # 图像二值化 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 形态学处理 kernel = np.ones((3, 3), np.uint8) dilation = cv2.dilate(binary, kernel, iterations=1) erosion = cv2.erode(dilation, kernel, iterations=1) # 轮廓提取 contours, _ = cv2.findContours(erosion, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) contoured_image = cv2.drawContours(image.copy(), contours, -1, (0, 255, 0), 2) # 抠图 mask = np.zeros(image.shape[:2], np.uint8) cv2.drawContours(mask, contours, -1, (255), -1) foreground = cv2.bitwise_and(image, image, mask=mask) # 更换背景 background = cv2.imread("background.png") background = cv2.resize(background, (image.shape[1], image.shape[0])) background = cv2.bitwise_and(background, background, mask=cv2.bitwise_not(mask)) # 合并图像 result = cv2.add(foreground, background) # 高斯模糊 result = cv2.GaussianBlur(result, (5, 5), 0) # 显示结果 cv2.imshow("Result", result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 以上代码中,需要将`image.png`替换为待处理的图像文件,`background.png`替换为更换的背景图像文件。其中,二值化阈值为127,形态学处理中膨胀和腐蚀的迭代次数均为1,高斯模糊的核大小为5x5。最后,将结果显示出来,并等待按下任意键关闭窗口。 ### 回答3: 下面是用Python编写的图像二值化、形态学处理轮廓提取、抠图、更换背景和进行高斯模糊的代码示例: ```python import cv2 import numpy as np def image_binarization(image): gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, binary_image = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY) return binary_image def morphology_processing(binary_image): kernel = np.ones((5, 5), np.uint8) closing = cv2.morphologyEx(binary_image, cv2.MORPH_CLOSE, kernel) return closing def extract_contours(image): contours, _ = cv2.findContours(image.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) return contours def extract_object(image, contours): mask = np.zeros_like(image) cv2.drawContours(mask, contours, -1, (255, 255, 255), thickness=cv2.FILLED) extracted_image = np.zeros_like(image) extracted_image[mask == 255] = image[mask == 255] return extracted_image def replace_background(image, background_image): image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) _, mask = cv2.threshold(image_gray, 10, 255, cv2.THRESH_BINARY) mask_inv = cv2.bitwise_not(mask) background = cv2.bitwise_and(background_image, background_image, mask=mask_inv) foreground = cv2.bitwise_and(image, image, mask=mask) result = cv2.add(background, foreground) return result def gaussian_blur(image): blurred_image = cv2.GaussianBlur(image, (5, 5), 0) return blurred_image # 示例用法 image = cv2.imread('input.jpg') binary_image = image_binarization(image) morphology_processed_image = morphology_processing(binary_image) contours = extract_contours(morphology_processed_image) object_image = extract_object(image, contours) background_image = cv2.imread('background.jpg') replaced_image = replace_background(object_image, background_image) blurred_image = gaussian_blur(replaced_image) cv2.imshow('Image', image) cv2.imshow('Binary', binary_image) cv2.imshow('Morphology Processed', morphology_processed_image) cv2.imshow('Object', object_image) cv2.imshow('Replaced', replaced_image) cv2.imshow('Blurred', blurred_image) cv2.waitKey(0) cv2.destroyAllWindows() ``` 这段代码使用OpenCV库进行图像处理。首先,将输入图像进行二值化处理,然后进行形态学闭操作,接着提取轮廓,抠出图像的主体部分,再将主体与新的背景图像进行替换,最后对结果图像进行高斯模糊处理。具体的每个函数实现了对应的功能,示例用法展示了如何将每个步骤的结果显示出来。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值