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

【python】【边缘提取】 亚像素轮廓跟踪,第1张

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

首先使用canny或其他方法将图片边缘轮廓提取:
(下图为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进行连线,为了方便观察,这里用较粗线条进行连接。
效果图:

效果较为满意。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5624893.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存