# python实现判断一个点是否在任意形状区域之射线交点法

python实现判断一个点是否在任意形状区域之射线交点法

import cv2 as cv
import numpy as np

# 全局变量
points = []  # 存储绘制的点
drawing = False  # 记录当前是否正在绘制

def mouse_callback(event, x, y, flags, param):
    global points, drawing

    if event == cv.EVENT_LBUTTONDOWN:
        drawing = True
        points = [(x, y)]  # 清空之前的点,开始新绘制
    elif event == cv.EVENT_MOUSEMOVE:
        if drawing:
            points.append((x, y))
    elif event == cv.EVENT_LBUTTONUP:
        drawing = False
        points.append((x, y))  # 结束绘制,包含最后一个点

def catmull_rom_spline(points, num_points=100):
    """ 使用Catmull-Rom样条生成平滑曲线 """
    if len(points) < 4:
        return np.array(points)
    
    t = np.linspace(0, 1, num_points)
    curve = []
    for i in range(1, len(points) - 2):
        p0, p1, p2, p3 = points[i-1:i+3]
        for j in t:
            x = 0.5 * ((2*p1[0]) + (-p0[0] + p2[0])*j +
                        (2*p0[0] - 5*p1[0] + 4*p2[0] - p3[0])*j*j +
                        (-p0[0] + 3*p1[0] - 3*p2[0] + p3[0])*j*j*j)
            y = 0.5 * ((2*p1[1]) + (-p0[1] + p2[1])*j +
                        (2*p0[1] - 5*p1[1] + 4*p2[1] - p3[1])*j*j +
                        (-p0[1] + 3*p1[1] - 3*p2[1] + p3[1])*j*j*j)
            curve.append((x, y))
    return np.array(curve)

def is_point_in_curve(point, curve_points):
    """ 使用射线交点法判断点是否在曲线内 """
    x, y = point
    num_points = len(curve_points)
    inside = False

    x1, y1 = curve_points[0]
    for i in range(num_points + 1):
        x2, y2 = curve_points[i % num_points]
        if y > min(y1, y2):
            if y <= max(y1, y2):
                if x <= max(x1, x2):
                    if y1 != y2:
                        xints = (y - y1) * (x2 - x1) / (y2 - y1) + x1
                    if x1 == x2 or x <= xints:
                        inside = not inside
        x1, y1 = x2, y2
    
    return inside

def main():
    global points

    cv.namedWindow("Draw Curve")
    cv.setMouseCallback("Draw Curve", mouse_callback)

    while True:
        img = np.ones((600, 800, 3), dtype=np.uint8) * 255  # 创建白色背景

        if len(points) > 1:
            # 生成平滑曲线
            curve_points = catmull_rom_spline(points)
            # 将曲线转为多边形,用于填充
            curve_points = np.array(curve_points, np.int32)
            curve_points = curve_points.reshape((-1, 1, 2))
            
            # 绘制曲线
            cv.polylines(img, [curve_points], isClosed=True, color=(0, 0, 255), thickness=2)
            # 填充曲线内部区域
            mask = np.zeros_like(img)  # 创建一个黑色背景的掩码
            cv.fillPoly(mask, [curve_points], color=(255, 0, 0))  # 蓝色填充
            img = cv.addWeighted(img, 1, mask, 0.5, 0)  # 0.5 透明度合成

        for pt in points:
            cv.circle(img, pt, 5, (0, 0, 255), -1)
        
        # 显示图像
        cv.imshow("Draw Curve", img)
        
        # 检测按键
        key = cv.waitKey(1) & 0xFF
        if key == ord('q'):
            break
        elif key == ord('c'):
            # 设定测试点位置
            test_point = (300, 300)  # 示例测试点
            if len(points) > 1:
                curve_points = catmull_rom_spline(points)
                is_inside = is_point_in_curve(test_point, curve_points)
                print(f"点 {test_point} 在曲线内: {is_inside}")

    cv.destroyAllWindows()

if __name__ == "__main__":
    main()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值