【python】【边缘提取】 亚像素轮廓跟踪

首先使用canny或其他方法将图片边缘轮廓提取:
(下图为mask处理后的图像)
mask图
参考论文
《A Sub-Pixel Edge Detector: an Implementation of theCanny/Devernay Algorithm》
提取后的亚像素级边缘散点如下:
在这里插入图片描述

由于亚像素级别的点太小,肉眼可能不好辨识,这边放一下局部效果图:
在这里插入图片描述

之后根据八邻域算法进行改进,提出了一种边缘亚像素点连线的方法:

import random

import cv2
from tqdm import tqdm

from json_open_close import open_json, save_json


# 获取两点间距离
def get_dis(x1, y1, x2, y2):
    return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5


# 获取相邻最近的三个结点
def get_nearest_nodes(x, y, new_locs):
    tem_dis = []
    for loc in new_locs:
        if not loc['visited']:
            tem_dis.append(((x - loc['loc'][0]) ** 2 + (y - loc['loc'][1]) ** 2) ** 0.5)
        else:
            tem_dis.append(1e5)
    _min = min(tem_dis)
    if _min > 200:
        return -1, -1, -1
    else:
        _index1 = tem_dis.index(_min)
        tem_dis[_index1] += 1e5
        _min = min(tem_dis)
        _index2 = tem_dis.index(_min)
        tem_dis[_index2] += 1e5
        _min = min(tem_dis)
        _index3 = tem_dis.index(_min)
        tem_dis[_index3] += 1e5
    return _index1, _index2, _index3


# 打开json格式存储的点位置文件
f = open_json("Pic1-3board.json")
locs = f['2']
length = len(locs)
new_locs = []

# 设置新的字典存储点位置
for i in range(length):
    tem = {
        "visited": False,
        "loc": locs[i],
        "id": 0,
        "end": False
    }
    new_locs.append(tem)

# 随机访问结点
start = random.randint(0, length - 1)
now_id = 0
new_locs[start]['id'] = now_id
new_locs[start]['visited'] = True
for i in tqdm(range(len(new_locs) - 1)):
    now_id += 1
    _index1, _index2, _index3 = get_nearest_nodes(new_locs[start]['loc'][0], new_locs[start]['loc'][1], new_locs)
    if _index1 == -1:
        new_locs[start]['id'] = now_id
        new_locs[start]['visited'] = True
        new_locs[start]['end'] = True
        count = 0
        for loc in new_locs:
            if not loc['visited']:
                start = count
                break
            count += 1
    else:
        _grad1 = (new_locs[start]['loc'][0] - new_locs[_index1]['loc'][0]) / (
                    new_locs[start]['loc'][1] - new_locs[_index1]['loc'][1] + 1e-6)
        _grad2 = (new_locs[start]['loc'][0] - new_locs[_index2]['loc'][0]) / (
                    new_locs[start]['loc'][1] - new_locs[_index2]['loc'][1] + 1e-6)
        _grad3 = (new_locs[start]['loc'][0] - new_locs[_index3]['loc'][0]) / (
                    new_locs[start]['loc'][1] - new_locs[_index3]['loc'][1] + 1e-6)
        dis1 = (new_locs[start]['loc'][0] - new_locs[_index1]['loc'][0]) ** 2 + (
                new_locs[start]['loc'][1] - new_locs[_index1]['loc'][1]) ** 2
        dis2 = (new_locs[start]['loc'][0] - new_locs[_index2]['loc'][0]) ** 2 + (
                new_locs[start]['loc'][1] - new_locs[_index2]['loc'][1]) ** 2
        dis3 = (new_locs[start]['loc'][0] - new_locs[_index3]['loc'][0]) ** 2 + (
                new_locs[start]['loc'][1] - new_locs[_index3]['loc'][1]) ** 2
        _grad1, _grad2, _grad3 = abs(_grad1), abs(_grad2), abs(_grad3)

        # 为每个结点打分
        score1 = dis1 * 0.9
        score2 = dis2 * 0.9
        score3 = dis3 * 0.9
        scores = (score1, score2, score3)
        # 选取最优结点
        _min = min(scores)
        _index = scores.index(_min)

        # 更新索引
        if _index == 0:
            start = _index1
        elif _index == 1:
            start = _index2
        else:
            start = _index3
        new_locs[start]['id'] = now_id
        new_locs[start]['visited'] = True
# 储存结果
save_json("new_loc.json", new_locs)

其中提取出的的数据格式为:

{
	"visited": true, 
	"loc": [12931, 911],
	"id": 901,
	"end": false
} 

使用cv.line进行连线,为了方便观察,这里用较粗线条进行连接。
效果图:
在这里插入图片描述
效果较为满意。

  • 6
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

赤赤赤赤赤赤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值