線分上のエッジとピークの検出¶
1次元エッジ検出とピーク探索により計測ライン(線分)上のエッジとピークを検出し、検出結果を画像として保存するサンプルコードです。
import pyfie
import numpy as np
import matplotlib.pyplot as plt
# 利便のため PyFIE 関数が返すエラーコードに応じて例外を発生させる機能を有効化
pyfie.ctrl.enable_f_err_exception(True)
# 入力画像読み込み
himg = pyfie.imread("edge1d_line_peaks_src.png")
# スキャンライン(1次元エッジ検出とピーク探索を行う範囲)を設定
scanline = pyfie.DSGMT_T((50, 50), (200, 200))
# 1次元エッジ検出用のデータ受け取り用変数を用意
MAX_EDGES = 10000
num_edges = pyfie.INT(MAX_EDGES)
edges = pyfie.F_DEDGE.ARRAY(num_edges)
# 1次元エッジ検出
pyfie.edge1d_line(
himg,
scanline,
prj_width=3,
filter_mode=pyfie.F_EDGE1D_DOG,
direct_mode=pyfie.F_DTC_BOTH,
diff_type=pyfie.F_RELATIVE_THR,
diff_thr=25,
sort_mode=pyfie.F_POS_SORT,
edges=edges,
edge_num=num_edges)
# 取得したエッジを表示
print("num edges:", num_edges)
for i, edge in enumerate(edges[:num_edges]):
print("#{}: x = {:.2f}, y = {:.2f}, mag = {:.2f}".format(
i, edge.x, edge.y, edge.mag
))
# 取得したエッジをプロットし結果画像として保存
himg.imshow()
scanline.plot(lw=1, color="blue")
edges.plot(num=num_edges, c="red", s=200, marker="+", zorder=4)
plt.savefig("edge1d_line_result.png")
plt.close()
# 1次元ピーク探索用の濃度プロファイルを作成
profile_len = pyfie.INT()
pyfie.edge1d_calc_projection_line_length(scanline, profile_len)
profile = pyfie.DOUBLE.ARRAY(profile_len)
valid_reg = pyfie.F_ARRAY_INDEX()
pyfie.edge1d_projection_line(
himg, scanline,
prj_width=3,
pprj=profile,
prj_len=profile_len,
valid_reg=valid_reg)
# 1次元ピーク探索用のデータ受け取り用変数を用意
num_peaks = pyfie.INT(profile_len)
peaks_val = pyfie.DOUBLE.ARRAY(num_peaks)
peaks_pos = pyfie.DOUBLE.ARRAY(num_peaks)
# 1次元ピーク探索
pyfie.find_peaks(
profile, profile_len,
neighbor=1,
nms_length=2,
rel_length=10,
val_thresh=10,
rel_thresh=5,
max_abs_diff=100,
sort_mode=0,
peaks_val=peaks_val,
peaks_pos=peaks_pos,
peaks_num=num_peaks)
# 濃度プロファイルにおけるピーク探索結果をプロットして保存
plt.plot(profile)
plt.scatter(peaks_pos[:num_peaks], peaks_val[:num_peaks], c="red")
plt.savefig("peaks_result_1d.png")
plt.close()
# 濃度プロファイルにおけるピークを元画像の座標に戻す
offset = np.array([scanline.st.x, scanline.st.y])
dirvec = np.array([scanline.ed.x, scanline.ed.y]) - offset
dirvec /= np.linalg.norm(dirvec)
peaks_pos_2d = pyfie.DPNT_T.ARRAY(num_peaks)
peaks_pos_2d.value = [
peak_pos_1d * dirvec + offset for peak_pos_1d in peaks_pos[:num_peaks]
]
# 取得したピークを表示
print("num peaks:", num_peaks)
for i, peak in enumerate(peaks_pos_2d):
print("#{}: x = {:.2f}, y = {:.2f}, mag = {:.2f}".format(
i, peak.x, peak.y, peaks_val[i]
))
# 取得したピークをプロットし結果画像として保存
himg.imshow()
scanline.plot(lw=1, color="blue")
peaks_pos_2d.plot(c="red", s=100, marker="+", zorder=4)
plt.savefig("peaks_result_2d.png")
plt.close()
処理結果例¶
$ python sample_edge1d_line_peaks.py
num edges: 3
#0: x = 104.22, y = 104.22, mag = 49.40
#1: x = 122.98, y = 122.98, mag = 84.93
#2: x = 171.81, y = 171.81, mag = 190.70
num peaks: 5
#0: x = 111.75, y = 111.75, mag = 153.23
#1: x = 126.65, y = 126.65, mag = 37.86
#2: x = 133.16, y = 133.16, mag = 42.93
#3: x = 144.17, y = 144.17, mag = 35.45
#4: x = 173.68, y = 173.68, mag = 242.37
入力画像

エッジ検出結果

ピーク検出結果

濃度プロファイル上のピーク検出結果
