识别图片中曲线并获取其坐标

2023-11-03

识别图片中曲线并获取其坐标

github主页:https://github.com/Taot-chen

有时候需要用到一些数据库里面曲线图的数据,进行进一步的变换处理,但是很多时候都只有图片,没有数据。基于这个问题,给出了以下算法。
思路:

 1)通过图像算法中常用的边界识别的方法来识别曲线;
 2)根据曲线上每一点的像素坐标和坐标轴的数值范围,来计算曲线上每一个像素点在坐标轴中的像素坐标。

实现过程:

一、曲线识别

1)图片预处理

思路:
 将待处理的图像转换成灰度图,在转换成二值图像;対二值图像的每一行和每一列的像素求和,根据像素和识别出图像的坐标轴范围;在坐标轴范围内遍历二值图像的每一列,将每列中像素值为0的像素下面的像素值全部置零。

原图:
[(img-PlRNIiCW-1636440564958)(“图片路径”, “原图”)]

具体实现:

将图像转换成二值图像:

    # 打开图片
    img = cv.imread(pic_name)
    # 灰度化
    gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 二值化
    # 此时的第二个和第三个参数,
    # 即二值化的上下阈值需要根据图片的实际情况个来调整
    ret, binary_img = cv.threshold(gray_img, 180, 255, cv.THRESH_BINARY)

识别坐标轴的范围:

    # 图像像素按行和列求和
    # 二值图像反相
    con_bi_img = 255 - binary_img
    column_sum_img = np.sum(con_bi_img, axis=0)
    row_sum_img = np.sum(con_bi_img, axis=1)
    
    # 排序
    sort_column_sum = np.sort(column_sum_img)
    sort_column_sum_indices = np.argsort(column_sum_img)
    sort_row_sum = np.sort(row_sum_img)
    sort_row_sum_indices = np.argsort(row_sum_img)
    
    print("列:\n")
    print(sort_column_sum[len(sort_column_sum) - 5:])
    print(sort_column_sum_indices[len(sort_column_sum_indices) - 5:])
    print("行:\n")
    print(sort_row_sum[len(sort_row_sum) - 5:])
    print(sort_row_sum_indices[len(sort_row_sum_indices) - 5:])

将曲线和坐标轴之间的区域设置成黑色:

for i in range(45, 773):
        flag = 0
        for j in range(73, 495):
            if binary_img[j][i] == 0:
                flag += j
                break
        for j in range(flag, 495):
            binary_img[j][i] = 0

预处理结果:
[(img-66BqlU2N-1636440564961)(“图片路径”, “预处理结果”)]

2)识别曲线

思路:
 通过对预处理的到图像进行边缘获取;识别出图像的坐标轴,在坐标轴范围内的边缘线就是所要识别的曲线。

具体实现:

边缘提取:

    # 边缘提取
    xgrd = cv.Sobel(binary_img, cv.CV_16SC1, 1, 0)
    ygrd = cv.Sobel(binary_img, cv.CV_16SC1, 0, 1
    egde_output = cv.Canny(xgrd, ygrd, 50, 150)

曲线获取:

    # 图像像素按行和列求和
    column_sum_img = np.sum(egde_output, axis=0)
    row_sum_img = np.sum(egde_output, axis=1)
    
    # 排序
    sort_column_sum = np.sort(column_sum_img)
    sort_column_sum_indices = np.argsort(column_sum_img)
    sort_row_sum = np.sort(row_sum_img)
    sort_row_sum_indices = np.argsort(row_sum_img)
    
    print(sort_column_sum[len(sort_column_sum) - 10:])
    print(sort_column_sum_indices[len(sort_column_sum_indices) - 10:])
    print(sort_row_sum[len(sort_row_sum) - 10:])
    print(sort_row_sum_indices[len(sort_row_sum_indices) - 10:])

    fc = egde_output[71:494, 47:770]

曲线识别结果:
[(img-SRwtfHfc-1636440564963)(“图片路径”, “曲线识别结果”)]

二、坐标计算

思路:

 根据原图的坐标范围与像素的对应关系来计算曲线上每一个像素的数值坐标。

具体实现:

    # 提取图像数据
    rows = (fc.shape)[0]
    cols = (fc.shape)[1]

    min_x = 4000
    max_x = 400
    min_y = 0.0
    max_y = 0.95

    x_axis = np.empty([rows, cols])
    y_axis = np.empty([cols, rows])

    # x_interval和y_interval用于调整数据长度,在报错的时候可以通过他们来调整
    x_interval = (max_x - min_x) / (cols + 1)
    x_value = np.arange(min_x + x_interval, max_x, x_interval)
    y_interval = (max_y - min_y) / (rows + 1)
    y_value = np.arange(max_y - y_interval, min_y, -y_interval)

    x_axis[:, ] = x_value
    y_axis[:, ] = y_value
    y_axis = y_axis.T

    x_fc = x_axis.T[fc.T == 255]
    y_fc = y_axis.T[fc.T == 255]

x_fc 和 y_fc 即为所求曲线的横坐标和纵坐标

曲线获取结果:
[(img-aC7heHzO-1636440564964)(“图片路径”, “曲线获取结果”)]

完整代码:
 为方便代码修改和阅读,上文中的几个步骤的实现分别在独立的文件中,共有三个文件。

./main.py

import get_curve as gc

pic_name = "the path of the original picture"
res = gc.get_points(pic_name)

./pic_prepro.py

import numpy as np
import cv2 as cv


def pre_pro(pic_name):
    # 打开图片
    img = cv.imread(pic_name)
    # 灰度化
    gray_img = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
    # 二值化
    # 此时的第二个和第三个参数,
    # 即二值化的上下阈值需要根据图片的实际情况个来调整
    ret, binary_img = cv.threshold(gray_img, 180, 255, cv.THRESH_BINARY)
    cv.imshow('binary_img', binary_img)
    cv.waitKey(0)
    cv.destroyAllWindows()

    # 图像像素按行和列求和
    # 二值图像反相
    con_bi_img = 255 - binary_img
    # print(np.shape(binary_img))
    cv.imshow('con_bi_img', con_bi_img)
    cv.waitKey(0)
    cv.destroyAllWindows()
    column_sum_img = np.sum(con_bi_img, axis=0)
    row_sum_img = np.sum(con_bi_img, axis=1)
    # 排序
    sort_column_sum = np.sort(column_sum_img)
    sort_column_sum_indices = np.argsort(column_sum_img)
    sort_row_sum = np.sort(row_sum_img)
    sort_row_sum_indices = np.argsort(row_sum_img)
    print("列:\n")
    print(sort_column_sum[len(sort_column_sum) - 5:])
    print(sort_column_sum_indices[len(sort_column_sum_indices) - 5:])
    print("行:\n")
    print(sort_row_sum[len(sort_row_sum) - 5:])
    print(sort_row_sum_indices[len(sort_row_sum_indices) - 5:])

    # 通过每一列和每一行像素和的输出值,判断坐标轴的位置
    # 在坐标轴范围内遍历每一列,将曲线下面的部分设置成黑色
    for i in range(45, 773):
        flag = 0
        for j in range(73, 495):
            if binary_img[j][i] == 0:
                flag += j
                break
        for j in range(flag, 495):
            binary_img[j][i] = 0
    cv.imshow('binary_img', binary_img)
    cv.waitKey(0)
    cv.destroyAllWindows()
    return binary_img

./get_curve.py

import numpy as np
from numpy.core.fromnumeric import shape
import cv2 as cv
import pic_prepro as pp


def get_points(picture_name):

    binary_img = pp.pre_pro(picture_name)
    cv.imshow('binary_img', binary_img)
    cv.waitKey(0)
    cv.destroyAllWindows()

    # 边缘提取
    xgrd = cv.Sobel(binary_img, cv.CV_16SC1, 1, 0)
    ygrd = cv.Sobel(binary_img, cv.CV_16SC1, 0, 1)

    egde_output = cv.Canny(xgrd, ygrd, 50, 150)
    cv.imshow('canny_edge', egde_output)
    cv.waitKey(0)
    cv.destroyAllWindows()

    # 图像像素按行和列求和
    column_sum_img = np.sum(egde_output, axis=0)
    row_sum_img = np.sum(egde_output, axis=1)
    # 排序
    sort_column_sum = np.sort(column_sum_img)
    sort_column_sum_indices = np.argsort(column_sum_img)
    sort_row_sum = np.sort(row_sum_img)
    sort_row_sum_indices = np.argsort(row_sum_img)
    print(sort_column_sum[len(sort_column_sum) - 10:])
    print(sort_column_sum_indices[len(sort_column_sum_indices) - 10:])
    print(sort_row_sum[len(sort_row_sum) - 10:])
    print(sort_row_sum_indices[len(sort_row_sum_indices) - 10:])

    fc = egde_output[71:494, 47:770]
    cv.imshow('function_curve', fc)
    cv.waitKey(0)
    cv.destroyAllWindows()

    # 提取图像数据
    rows = (fc.shape)[0]
    cols = (fc.shape)[1]

    min_x = 4000
    max_x = 400
    min_y = 0.0
    max_y = 0.95

    x_axis = np.empty([rows, cols])
    y_axis = np.empty([cols, rows])

    # x_interval和y_interval用于调整数据长度,在报错的时候可以通过他们来调整
    x_interval = (max_x - min_x) / (cols + 1)
    x_value = np.arange(min_x + x_interval, max_x, x_interval)
    y_interval = (max_y - min_y) / (rows + 1)
    y_value = np.arange(max_y - y_interval, min_y, -y_interval)

    x_axis[:, ] = x_value
    y_axis[:, ] = y_value
    y_axis = y_axis.T

    x_fc = x_axis.T[fc.T == 255]
    y_fc = y_axis.T[fc.T == 255]

    return (x_fc, y_fc)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

识别图片中曲线并获取其坐标 的相关文章

随机推荐

  • 奥的斯电梯服务器不显示菜单,奥的斯电梯调试服务器按键介绍.doc

    奥的斯电梯调试服务器按键介绍 doc 由会员分享 可在线阅读 更多相关 奥的斯电梯调试服务器按键介绍 doc 2页珍藏版 请在文库网上搜索 1 奥的斯电梯调试服务器 俗称ST 按键介绍 奥的斯电梯调试服务器 俗称ST 按键介绍 ST的前面板
  • 高阶函数 /内联函数/高阶函数中使用内联函数/闭包函数/内置高阶函数( let、also、with、run、apply )

    一 高阶函数 高阶函数的定义 高阶函数是指将一个函数作为另一个函数的参数或者将一个函数作为另一个函数的返回值 与java不同的是 在Kotlin中增加了一个函数类型的概念 如果我们将这种函数添加到另一个函数的参数声明或返回值声明当中 那么这
  • Mac及Xcode使用相关问题记录

    1 连接samba服务器 方法 finder gt 前往 gt 连接服务器 输入服务器地址smb 169 254 43 44 连接即可 2 xcode设置快捷键 xcode gt Prefrences gt Key Bindings 修改如
  • 程序中有游离的‘\240’ ‘\302’问题的解决方法

    错误 程序中有游离的 240 302 sed i s o240 o302 g test c
  • oracle问题排查

    目录 问题1 ORA 01017 invalid username password logon denied 问题2 链接普通用户报错ORA 01034 ORACLE not available 问题1 ORA 01017 invalid
  • 独自封装windows 10系统详细教程(一)

    目录 作者语录 一 封装前准备工具 二 安装Windows系统 1 创建虚拟机环境 2 更改BIOS启动顺序 3 安装windows系统 作者语录 这篇文章从无到有 从小白到会轻轻松松的事 超级详细的过程 方面你们操作实践 对你们有用的给我
  • 【C/C++】输出格式%d、%6d、%06d、%-6d、%.6f的区分

    C C 输出格式 d 6d 06d 6d 6f的区分 文章目录 C C 输出格式 d 6d 06d 6d 6f的区分 1 d 普通的整数输出 2 6d 整数输出 宽度是6位 不足左边补空格 3 06d 整数输出 宽度是6位 不足左边补数字0
  • Linux的命令——“cd”(内附Linux命令格式,相对路径和绝对路径)

    内容预知 目录 1 Linux的 命令格式书写 1 2 选项的用法 1 3 参数 2 绝对路径与相对路径 3 对终端中默认 root localhost 的认识 4 七种文件类型 5 命令cd 总结 1 Linux的 命令格式书写 1 1
  • S5PV210开发1.0.5----重定位relocate与SDRAM

    目录 1 5 1 关看门狗 1 5 2 设置栈 调用C语言 1 5 3 开iCache 1 5 4 重定位及其代码实战 1 5 5 SDRAM介绍 1 用汇编关看门狗 1 1 什么是看门狗 watch dog timer 定时器 Soc的内
  • nginx resolver

    背景 nginx 配置proxy pass后 访问接口出现no resolver defined to resolve错误 或者接口直接502 404 需要配置 nginx resolver server server name wfk m
  • 使用jetty-maven-plugin插件进行测试

    为了能够使用maven的jetty插件对项目进行测试 需要进行如下操作 1 修改maven配置文件 为了能够在命令行中使用jetty命令 需要修改maven的配置文件settings xml文件 添加如下配置代码 html view pla
  • 关于Incapsula reese84加密的特征研究

    最近研究了下reese84的加密算法 基本上两个参数的加密 utmvc和token 因为nodejs调用会有内存问题 没有采用补环境的方式解决 用python扣的算法 1 utmvc参数的生成是一个ob混淆 ast处理之后调试难度不是很大
  • tensorflow学习笔记(3)——基础(三)——TF训练和变量

    5 tensorflow实现神经网络 1 TF游乐场及神经网络简介 TF游乐场 http playground tensorflow org 略 使用神经网络解决分类问题的主要步骤 1 提取特征向量作为输入 2 定义神经网络结构 得到输出
  • vue3+ts+mock

    项目地址 使用vite创建的vue3 ts项目 集成了mock vuex 项目截图 修改主题 项目克隆及运行 克隆 git clone https gitee com liwensa vue3 tsmock git 进入项目运行 npm i
  • 深度学习中常见的损失函数

    目录 一 损失函数的定义 二 常见的回归损失函数 1 L1 LOSS MAE平均绝对误差 2 L2 LOSS MSE均方差误差 3 Smooth L1 LOSS 4 IOU LOSS及其各种变种 三 常见的分类损失函数 1 交叉熵损失函数
  • Linux删除含有特殊符号文件名的文件

    1 使用 ls i 查处该文件的 inode 号 假设为123 2 使用find命令删除 rm find inum 123 如果是目录 rm rvf find inum 123
  • Going deeper with convolutions(InceptionNet)

    进一步深化卷积 Abstract 摘要 我们提出了一个代号为Inception的深度卷积神经网络架构 该架构负责设置2014年ImageNet大规模视觉识别挑战赛 ILSVRC14 中用于分类和检测的新技术 该体系结构的主要标志是提高了网络
  • 一个例子理解梯度下降法(附梯度下降法与最小二乘法比较)

    一个例子理解梯度下降法 例子描述 梯度下降法简介 基于python3 matplotlib的实现代码 梯度下降法实现 最小二乘法实现 比较结果 总结 最近听课时 AI导论老师留下了一个简单的线性回归例子 这个例子属于单变量线性回归 可以用梯
  • Ajax入门

    文章目录 axios体验 axios 查询参数 常用请求方法 数据提交 axios错误处理 axios体验 引入axios库 使用axios语法 axios url 目标资源地址 then result gt 对服务器返回的数据做后续处理
  • 识别图片中曲线并获取其坐标

    识别图片中曲线并获取其坐标 github主页 https github com Taot chen 有时候需要用到一些数据库里面曲线图的数据 进行进一步的变换处理 但是很多时候都只有图片 没有数据 基于这个问题 给出了以下算法 思路 1 通