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

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

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)
  • 10
    点赞
  • 127
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
### 回答1: 光谱分布到色坐标的转换是指将光谱分布数据转换成对应的色坐标值。色坐标是一种用来描述颜色的数值表示方法,常用于显示设备和光学系统。 在进行光谱分布到色坐标的转换时,首先需要获取与光谱分布相对应的色度图谱。色度图谱是一种将光谱能量分布转换成色度量的图表,一般通过实验或仿真计算获得。然后,根据色度图谱的数据,进行插值计算或数学模型拟合,将光谱分布的不同波长对应的能量值映射到色度图谱的对应位置上。最后,从色度图谱获取到对应位置的色度坐标值,即可得到光谱分布到色坐标的转换结果。 光谱分布到色坐标的转换在实际应用具有很广泛的应用价值。例如,我们可以通过该转换将光电传感器测量得到的光谱数据转换为RGB或CMYK色彩空间的颜色表示,从而实现画面的显示和分析。在光学系统,可以根据光谱分布来优化滤波器的设计,以实现特定色彩的显示效果。在光谱分析,将光谱分布转换成色坐标可以更直观地描述样本的色泽特征,对于色彩分析和识别非常有帮助。 总之,光谱分布到色坐标的转换是一种可将光谱分布数据转换成对应的色度坐标的方法,广泛应用于显示设备、光学系统和光谱分析。 ### 回答2: 光谱分布到色坐标的转换通常是通过色度图来实现的。色度图是一种以色彩为基础的二维平面,可以将不同波长的光谱信息转换成由色坐标表示的颜色特征。 光谱分布通常用波长来描述,而色坐标则用于表示人眼所感知到的颜色。人眼能够感知的光的波长范围大约在380-780纳米之间,而光谱分布则可以包含更广泛的范围。为了将光谱分布转换为色坐标,首先需要选择一个适当的色度图,其色度图的坐标值与波长之间有明确的对应关系。 对于整个光谱分布,可以用色度图的颜色块进行覆盖,并根据每个颜色块对应的波长范围和光强度来计算在每个颜色块所占的比例。通过对所有颜色块的比例进行加权求和,即可得到整个光谱分布所对应的色坐标。 需要注意的是,转换的准确性和精度受到色度图的选择和色度图分辨率的影响。不同的色度图可以提供不同的色彩细节和精度。同时,转换还受到人眼对不同波长的敏感度的影响,因此在进行光谱到色坐标的转换时,可能需要考虑人眼对不同波长的感知特性。 总之,光谱分布到色坐标的转换是一项复杂的任务,需要根据色度图和人眼对不同波长的敏感度来进行计算和估算。这一转换可以帮助我们更直观地理解光谱分布的颜色信息。 ### 回答3: 光谱分布到色坐标的转换是指将光的光谱分布转换为色彩在色坐标的表示。光谱是由波长不同的光线组成的,每种波长的光线都对应着一种颜色。但是人类的眼睛并不是对所有波长的光线都敏感,只有在可见光波段内的光线才能被我们感知到。 色坐标是一种用来表示颜色的方式,常用的色坐标系统有CIE XYZ色彩空间和CIE Lab色彩空间等。在色彩空间,每个颜色都可以由相应的坐标表示,通常用(x,y)或(L,a,b)来表示。 光谱到色坐标的转换需要借助人类视觉系统对光的感知过程。人的视觉系统对不同波长的光线的感知程度是不一样的,所以需要进行一定的加权处理。CIE色彩空间是根据人眼的感知特性设计的,其CIE XYZ色彩空间是最早提出的一种色彩空间。 将光谱分布转换为色坐标的过程通常通过光谱重建算法实现。该算法通过将光谱的各个波长分量与人眼感知的响应曲线进行相乘,然后再对结果进行积分,最后得到对应的色彩坐标。 光谱到色坐标的转换在颜色测量和显示技术有着重要的应用。通过光谱分布到色坐标的转换,我们可以精确地描述和控制颜色,使得不同设备之间的颜色呈现更加一致。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值