图像转svg,及绘制svg图像

                                                                                           图像转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=================================================

图像转svg,及绘制svg图像_第1张图片

01.svg.py

# 读取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 - 1.5 * (y -translate_int)
        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图片存在位移问题
        #py = self.getChangF(py,translate)
        #3.通过原始图像py坐标与原始画布h宽度的比例计算出映射画布的图像y坐标
        y =  py * y_p/ h
        return x,y

你可能感兴趣的:(python,图像转svg,svg)