图像转svg,及绘制svg图像

tech2023-07-27  114

                                                                                           图像转svg

1:生成svg图

sudo apt install potrace

 

python import os def t(img_path): """ img转svg方法 :param img_path: img路径 :return: 返回output.svg绝对路径 """ os.system("convert " + img_path + " output_tmp.ppm") os.system("potrace output_tmp.ppm -b svg -u 1 --flat -o output.svg") os.system("rm output_tmp.ppm") return "{}/output.svg".format(os.popen("pwd").readline().rstrip('\r\n'))

 生成svg图格式会发生y轴位移,导致打印图片的坐标不准确

解决公式:

得到正确的坐标

y-2*(y+213*(-1))

 通过解析得到 y轴偏移,然后计算y轴正确坐标

doc = minidom.parse('svg/che.svg') # 2.查找path标签 paths = doc.getElementsByTagName('path') svgTag = doc.getElementsByTagName('svg') w = svgTag[0].getAttribute('width') h = svgTag[0].getAttribute('height') print(type(w),h) ##获取位移与缩放比例,代码转的svg注意图片是否存在位移,存在的需要获取位移信息 gs = doc.getElementsByTagName('g') ## 获取位移的y坐标 translate_y="0" scales="0" translates_scales=gs[0].getAttribute('transform').split(" ") if len(translates_scales)>1: translates,scales=translates_scales print(translates.find("(")) print(scales.find("(")) #位移 translate_x,translate_y=translates[translates.find("(")+1:len(translates)-1].split(',') #缩放比例 scales=scales[scales.find("(")+1:len(scales)-1].split(',') print("========================") print(translate) ##算y轴正确坐标 def getChangF(self,y,translate_y): #如y轴坐标小数点后面后数字或字母,把点后面的数据截取掉 translate_index = translate_y.find(".") translate_int = int(translate_y[:translate_index if (translate_index > 1) else len(translate_y)]) if (translate_int > 0): y = y - 2 * (y -translate_int*(-1)) return y

 

=====================================预览svg=================================================

01.svg.py  解析svg

# 读取svg的xml文件 from xml.dom import minidom # 解析svg路径 from svg.path import parse_path import numpy as np import cv2 as cv import random # 1.读取xml文件 doc = minidom.parse('svg/che.svg') # 2.查找path标签 paths = doc.getElementsByTagName('path') svgTag = doc.getElementsByTagName('svg') w = svgTag[0].getAttribute('width') h = svgTag[0].getAttribute('height') print(type(w),h) ##获取位移与缩放比例,代码转的svg注意图片是否存在位移,存在的需要获取位移信息 gs = doc.getElementsByTagName('g') ## 获取位移的y坐标 translate_y="0" scales="0" translates_scales=gs[0].getAttribute('transform').split(" ") if len(translates_scales)>1: translates,scales=translates_scales print(translates.find("(")) print(scales.find("(")) #位移 translate_x,translate_y=translates[translates.find("(")+1:len(translates)-1].split(',') #缩放比例 scales=scales[scales.find("(")+1:len(scales)-1].split(',') print("========================") print(translate) # 定义列表 保存所有的path的d属性 pip3 install svg.path pathsList = [] for path in paths: pathsList.append(path.getAttribute('d')) # ------------------------- 颜色 -------------------------# RED = (0, 0, 255) # 随机颜色 def randomColor(): return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255) # ------------------------- 绘制 -------------------------# dst = np.zeros((1920, 1080, 3), dtype=np.uint8) # ------------------------- 绘制move -------------------------# def drawMove(ele): start = int(ele.start.real), int(ele.start.imag) cv.line(dst, start, start, randomColor()) cv.imshow('dst', dst) cv.waitKey(5) # ------------------------- 绘制直线 -------------------------# # Line(start=(424.81453999999997+371.04679000000004j), end=(424.81453999999997+369.04679000000004j)) def drawLine(ele): start = int(ele.start.real), int(ele.start.imag) end = int(ele.end.real), int(ele.end.imag) cv.line(dst, start, end, RED) cv.imshow('dst', dst) cv.waitKey(5) # ------------------------- 绘制二阶贝塞尔 -------------------------# def QuadraticBezier(ps, pc, pe, t): ''' 获取二阶贝塞尔点 :param ps: 开始点 :param pc: 控制点 :param pe: 结束点 :param t: 0-1 :return: ''' return pow(1 - t, 2) * ps + 2 * t * (1 - t) * pc + pow(t, 2) * pe def drawQuadraticBezier(ele): # 开始点 ps = np.array([ele.start.real, ele.start.imag]) # 控制点 p = np.array([ele.control.real, ele.control.imag]) # 结束点 pe = np.array([ele.end.real, ele.end.imag]) point = QuadraticBezier(ps, p, pe, 0) start = int(point[0]), int(point[1]) # 40个点 for i in range(1, 41): result = QuadraticBezier(ps, p, pe, i / 40) end = int(result[0]), int(result[1]) # 连接两个点 cv.line(dst, start, end, randomColor()) cv.imshow('dst',dst) cv.waitKey(5) # 开始点变成结束点 start = end # ------------------------- 三阶贝塞尔 -------------------------# def CubicBezier(ps, pc1, pc2, pe, t): ''' 获取二阶贝塞尔点 :param ps: 开始点 :param pc: 控制点 :param pe: 结束点 :param t: 0-1 :return: ''' return pow(1 - t, 3) * ps + 3 * t * pow(1 - t, 2) * pc1 + 3 * pow(t, 2) * (1 - t) * pc2 + pow(t, 3) * pe def drawCubicBezier(ele): print('绘制贝塞尔') # 开始点 ps = np.array([ele.start.real, ele.start.imag]) # 控制点 p1 = np.array([ele.control1.real, ele.control1.imag]) p2 = np.array([ele.control2.real, ele.control2.imag]) # 结束点 pe = np.array([ele.end.real, ele.end.imag]) result = CubicBezier(ps, p1, p2, pe, 0) print(result) start = int(result[0]),int(result[1]) # 40个点 for i in range(1,41): result = CubicBezier(ps, p1, p2, pe, i / 40) end = int(result[0]),int(result[1]) # 连接两个点 cv.line(dst,start,end,randomColor()) cv.imshow('dst',dst) cv.waitKey(5) # 开始点变成结束点 start = end #------------------------- 结束点 -------------------------# def drawClose(ele): start = int(ele.start.real), int(ele.start.imag) end = int(ele.end.real), int(ele.end.imag) cv.line(dst, start, end, randomColor()) cv.imshow('dst', dst) cv.waitKey(5) # 解析路径字符串 for path in pathsList: result = parse_path(path) print(result) # path 序列 可以通过for循环获取所有的元素 for ele in result: print(type(ele).__name__) if type(ele).__name__ == 'Move': drawMove(ele) elif type(ele).__name__ == 'Line': drawLine(ele) elif type(ele).__name__ == 'CubicBezier': drawCubicBezier(ele) elif type(ele).__name__ == 'QuadraticBezier': drawQuadraticBezier(ele) elif type(ele).__name__ == 'Close': drawClose(ele) else: print('其他') cv.waitKey(0)

 

 ##坐标转换

def getChangF(self,y,translate): #位移 translate_index = translate.find(".") translate_int = int(translate[:translate_index if (translate_index > 1) else len(translate)]) if (translate_int > 0): y = y - 2 * (y -translate_int*(-1)) return y def scaleData_with_wh_svg(self,px,py,w,h): ''' 对数据缩放处理 :param cal: :return: px :原图像x坐标 py :原图像y坐标 w :原图像所在的画布宽度 h :原图像所在的画布宽度 映射的画布尺寸 w:640 h: 480 1.取最小的(高度最小) h: y_p高度尺寸,按原始画布的宽高比例计算出宽度尺寸x_p 2.通过原始图像px坐标与原始画布w宽度的比例计算出映射画布的图像x坐标 3.通过原始图像py坐标与原始画布h宽度的比例计算出映射画布的图像y坐标 ''' h_index=h.find(".") w_index = w.find(".") h=int(h[:h_index if (h_index>1) else len(h)]) w=int(w[:w_index if (w_index>1) else len(w)]) #1.取最小的(高度最小) h: y_p高度尺寸, 按原始画布的宽高比例计算出宽度尺寸x_p y_p = 460 x_p = y_p * w / h #2.通过原始图像px坐标与原始画布w宽度的比例计算出映射画布的图像x坐标 x = px *x_p / w ##代码转的svg图片存在位移问题 ##算y轴正确坐标 y-2*(y+213*(-1)) #py = self.getChangF(py,translate) #3.通过原始图像py坐标与原始画布h宽度的比例计算出映射画布的图像y坐标 y = py * y_p/ h return x,y
最新回复(0)