MagickWandバインディングライブラリを使用して、AutoCADのDXFファイルを高解像度のバイレベルTIFFファイルに変換するPythonスクリプトに取り組んでいます。スクリプトは期待どおりに動作しますが、パフォーマンスを改善する方法を探しています。
スクリプトは次のとおりです。
import dxfgrabber
import cv2
import numpy as np
import sys
from wand.image import Image
RESOLUTION_DPI = 1000
def drawPolyLines(pl):
if(pl.is_closed):
points = []
for pt in pl.points:
points += [[xToPix(pt[0]),yToPix(pt[1])]]
points = np.array(points,np.int32)
cv2.fillPoly(canvas,[points],0,cv2.LINE_8)
dxf = dxfgrabber.readfile("812b.dxf")
shapes = dxf.entities.get_entities()
in_limMin = dxf.header['$LIMMIN']
in_limMax = dxf.header['$LIMMAX']
pix_limMin = tuple([int(z * RESOLUTION_DPI) for z in in_limMin])
pix_limMax = tuple([int(z * RESOLUTION_DPI) for z in in_limMax])
#Translate x,y values to pixels
def xToPix(coord):
return int((coord*RESOLUTION_DPI))
def yToPix(coord, ymax=pix_limMax[1]):
return int(ymax - (coord*RESOLUTION_DPI))
canvas = np.zeros((pix_limMax[1],pix_limMax[0]), np.uint8)
canvas.fill(1)
for shape in shapes:
if shape.dxftype == 'POLYLINE':
drawPolyLines(shape)
with Image.from_array(canvas) as img:
img.resolution = RESOLUTION_DPI
img.compression='rle'
img.type='bilevel'
img.depth = 1
img.save(filename='result.tif')
1 つのファイルを変換するのに約 30 秒かかります。これを改善したいと考えています。累積時間でソートされた cProfile は、次のことを示しています。
$ python -m cProfile -s 'cumtime' test.py
324966 function calls (322147 primitive calls) in 37.550 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
488/1 0.001 0.000 37.557 37.557 {built-in method builtins.exec}
1 0.000 0.000 37.557 37.557 test.py:1(<module>)
3 0.000 0.000 31.180 10.393 image.py:1013(wrapped)
1 30.500 30.500 30.500 30.500 image.py:2451(type)
1 4.329 4.329 4.329 4.329 image.py:9251(save)
1 1.485 1.485 1.487 1.487 image.py:8754(from_array)
1 0.681 0.681 0.681 0.681 image.py:1629(depth)
16 0.001 0.000 0.446 0.028 __init__.py:1(<module>)
208/5 0.002 0.000 0.229 0.046 <frozen importlib._bootstrap>:986(_find_and_load)
207/5 0.001 0.000 0.228 0.046 <frozen importlib._bootstrap>:956(_find_and_load_unlocked)
197/6 0.001 0.000 0.225 0.038 <frozen importlib._bootstrap>:650(_load_unlocked)
160/6 0.000 0.000 0.225 0.037 <frozen importlib._bootstrap_external>:777(exec_module)
290/6 0.000 0.000 0.221 0.037 <frozen importlib._bootstrap>:211(_call_with_frames_removed)
330/3 0.001 0.000 0.179 0.060 {built-in method builtins.__import__}
198/23 0.000 0.000 0.173 0.008 <frozen importlib._bootstrap>:1017(_handle_fromlist)
197/58 0.000 0.000 0.161 0.003 <frozen importlib._bootstrap>:549(module_from_spec)
22/3 0.000 0.000 0.159 0.053 <frozen importlib._bootstrap_external>:1099(create_module)
22/3 0.029 0.001 0.159 0.053 {built-in method _imp.create_dynamic}
1 0.000 0.000 0.158 0.158 __init__.py:41(readfile)
1 0.000 0.000 0.158 0.158 __init__.py:52(readfile_as_asc)
1 0.000 0.000 0.116 0.116 __init__.py:61(_read_encoded_file)
1 0.110 0.110 0.110 0.110 {method 'fill' of 'numpy.ndarray' objects}
ご覧のとおり、実行時間のほぼ全体が、イメージ タイプをバイレベルに設定する結果の呼び出しに費やされています。MagickWand のソースを少し掘り下げたところ、SetImageType()
メソッドが内部から呼び出されたときに行き止まりが見つかりましたMagickImage.MagickSetImageType()
。すべてのピクセルを単一のビット値に変換するしきい値操作があるかどうか疑問に思っています。これはおそらく時間がかかり、この場合は行列の値が 0 または 1 しかないため意味がありません。残念ながら、opencv 描画メソッドには 8 ビット整数型が必要であり、MagickW に入力できる別のデータ型があるかどうかわかりません。パフォーマンスが向上します。この操作を高速化するための提案を探しています。ありがとう。