こんてんつ
画像内のフチを抽出してCAD(.dxf)ファイルとして出力する方法をまとめる。
- 結論(完成系)
- コード(画像のアップロードと表示)
- コード(輪郭抽出とmerge)
- コード(.dxf出力)
結論(完成系)
例題
下記の画像から輪郭を抽出する。
コード
Google Colaboratoryを利用して実装する。
import cv2 import numpy as np from google.colab import files from matplotlib import pyplot as plt ### 画像のアップロードと表示 uploaded_file = files.upload() uploaded_file_name = next(iter(uploaded_file)) orig = cv2.imread(uploaded_file_name) src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB) plt.axis('off') plt.imshow(src) ### 輪郭を作成して元の画像にmerge frame = cv2.imread(uploaded_file_name) canny = cv2.Canny(frame, 255, 0) contours, hierarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) contours_draw = cv2.drawContours(frame, contours, -1, (0, 255, 0), 1) merged_file_name = "merged.jpg" cv2.imwrite(merged_file_name, contours_draw) orig = cv2.imread(merged_file_name) src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB) plt.axis('off') plt.imshow(src) ### 輪郭部分のみを取り出してdxfファイルを出力する import ezdxf dwg = ezdxf.new("R2010") msp = dwg.modelspace() dwg.layers.new(name="greeny green lines", dxfattribs={"color": 3}) squeezed = [np.squeeze(cnt, axis=1) for cnt in contours] inverted_squeezed = [arr * [1, -1] for arr in squeezed] for ctr in inverted_squeezed: for n in range(len(ctr)): if n >= len(ctr) - 1: n = 0 try: msp.add_line(ctr[n], ctr[n + 1], dxfattribs={"layer": "greeny green lines", "lineweight": 20}) except IndexError: pass dwg.saveas('output.dxf')
コードを少し解説
画像のアップロードと表示
import cv2 import numpy as np from google.colab import files from matplotlib import pyplot as plt uploaded_file = files.upload() uploaded_file_name = next(iter(uploaded_file)) orig = cv2.imread(uploaded_file_name) src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB) plt.axis('off') plt.imshow(src)
プログラムが途中で止まって、アップロードする画像のファイルを選択するよう指示される。
画像をアップロードしたら、次のように表示される。
輪郭抽出とmerge
import cv2 import numpy as np from google.colab import files from matplotlib import pyplot as plt ### 画像のアップロード uploaded_file = files.upload() uploaded_file_name = next(iter(uploaded_file)) ### 輪郭の作成 frame = cv2.imread(uploaded_file_name) canny = cv2.Canny(frame, 255, 0) contours, hierarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) contours_draw = cv2.drawContours(frame, contours, -1, (0, 255, 0), 1) ### merge merged_file_name = "merged.jpg" cv2.imwrite(merged_file_name, contours_draw) ### 画像の表示 orig = cv2.imread(merged_file_name) src = cv2.cvtColor(orig, cv2.COLOR_BGR2RGB) plt.axis('off') plt.imshow(src)
merged.jpg
を確認すると、輪郭が緑線で付けられていることが分かる。
CAD(.dxf)出力
import cv2 import numpy as np from google.colab import files from matplotlib import pyplot as plt ### 画像のアップロード uploaded_file = files.upload() uploaded_file_name = next(iter(uploaded_file)) ### 輪郭の作成 frame = cv2.imread(uploaded_file_name) canny = cv2.Canny(frame, 255, 0) contours, hierarchy = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) contours_draw = cv2.drawContours(frame, contours, -1, (0, 255, 0), 1) ### 輪郭部分のみを取り出してdxfファイルを出力する import ezdxf dwg = ezdxf.new("R2010") msp = dwg.modelspace() dwg.layers.new(name="greeny green lines", dxfattribs={"color": 3}) squeezed = [np.squeeze(cnt, axis=1) for cnt in contours] inverted_squeezed = [arr * [1, -1] for arr in squeezed] for ctr in inverted_squeezed: for n in range(len(ctr)): if n >= len(ctr) - 1: n = 0 try: msp.add_line(ctr[n], ctr[n + 1], dxfattribs={"layer": "greeny green lines", "lineweight": 20}) except IndexError: pass dwg.saveas('output.dxf')
output.dxf
というCADファイルが作成されている。