fullseye

OpenVX の素の口 — 使い方ガイド

Copyright (c) 2026 Kazufumi Furuse.

この族は何をする道具箱か

OpenVX 1.3.1(Khronos の視覚処理 API の規格)は、視覚関数ごとに何を受け取り何を返すかを番号つきの規範文 [REQ-NNNN] で決めています。 2026-09-25 に 61 本を本文まで読んで照合したら、17 本は「Fullseye にも似た op はあるが、入口か出口の形が違う」でした。たとえば sobel_mag は 大きさを [0, 1] に正規化して返すので、規格の順序 —— Sobel で gx と gy を出し、別々に大きさと位相へ —— では使えません。

この族は、その素の口を規範文どおりに開けます(合成 op は消しません)。第 1 陣 6 op と第 2 陣 4 op:

画像は U8 / S16 の dtype を規格どおりに受け、合わなければ止めます(黙って丸めません)。

代表的なパイプライン

flowchart LR
  U8[U8 画像] --> S[vx_sobel3x3]
  S -->|gx| M[vx_magnitude]
  S -->|gy| M
  S -->|gx| P[vx_phase]
  S -->|gy| P
  M --> N[vx_nonmax_suppression]
  U8 --> H[vx_histogram]
  U8 --> L[vx_table_lookup]

使い方(最小の 1 本)

import numpy as np
import vxcore as V

img = np.zeros((7, 9), np.uint8)
img[:, 4:] = 100                                                   # 縦の段差(左 0 → 右 100)
g = V.vx_sobel3x3(img, border="replicate")                         # REQ-0415 の核、gx と gy を別々に
print(g["gx"][3, 2:7].tolist(), int(g["gy"].max()))      # [0, 400, 400, 0, 0] 0
mag = V.vx_magnitude(g["gx"], g["gy"])                             # REQ-0270: sqrt + 0.5 を切り捨て、32767 で飽和
print(mag[3, 3:5].tolist(), V.vx_phase(g["gx"], g["gy"], mapping="floor")[3, 3])   # [400, 400] 0(右向きの勾配 = 位相 0)
peaks = V.vx_nonmax_suppression(mag, window=3)                     # REQ-0337: 前の隣に ≥、後ろの隣に >
print(int((peaks > 0).sum()))          # 1 —— 幅 2・長さ 7 の平らな稜線が右下の 1 画素に潰れる
print(V.vx_histogram(img, num_bins=4, offset=0, range_=256)[:, 1].tolist())        # [28.0, 35.0, 0.0, 0.0] —— REQ-0230 の升

気をつけること

真値

試験(tests/test_vxcore.py)は、規範文の式を画素ごとの素朴なループで写した別の実装と突き合わせます: Sobel は scipy の相関、大きさは REQ-0270 の C の式、 位相は math.atan2、ヒストグラムは REQ-0230 の式、非極大の抑制は 3.39 節の 8 つの不等式。≥ と > を入れ替えた壊れた版で 3 件落ちることも確かめてあります。