Welding:SurfaceSampleDataGenerator
LVS로 부터 (x, z) 축만 있는 csv 데이터 1-Line을 y축으로 여러 라인을 추가한, "면 (Surface)" 가상 데이터로 ply로 생성하는 방법.
Sample Data
Micro-Epsilon:scanCONTROL 을 사용함:
| |
다음과 같은 용접면을 스캔 하였다:
| |
다음과 같은 csv 파일을 획득할 수 있다:
전체 데이터 샘플은 20260415-butt_bead_profile_sample.zip 이다.
X, Z 축만 있는 CSV 데이터 변환하기
LVS 같은 레이저 스캐너를 통해 데이터를 얻으면 (x, z) 좌표만 얻어진다. 이걸 3차원 ply 로 표현하기 위해 y 축을 추가해 준다:
import csv
import sys
import os
def convert_csv_to_ply(csv_path, ply_path):
points = []
with open(csv_path, 'r') as f:
reader = csv.reader(f)
for row in reader:
if len(row) >= 2:
try:
x = float(row[0])
y = 0.0 # 단일 프로파일이므로 y는 0으로 고정
z = float(row[1])
points.append((x, y, z))
except ValueError:
continue
with open(ply_path, 'w') as f:
f.write("ply\n")
f.write("format ascii 1.0\n")
f.write(f"element vertex {len(points)}\n")
f.write("property float x\n")
f.write("property float y\n")
f.write("property float z\n")
f.write("end_header\n")
for p in points:
f.write(f"{p[0]} {p[1]} {p[2]}\n")
if __name__ == "__main__":
files = [
"20260415-butt_bead_profile_sample.csv",
"20260415-fillet_bead_profile_sample.csv"
]
for csv_file in files:
if os.path.exists(csv_file):
ply_file = csv_file.replace(".csv", ".ply")
convert_csv_to_ply(csv_file, ply_file)
print(f"Converted {csv_file} -> {ply_file}")
여러 스캔 라인 생성하기
제공해주신 CSV 데이터와 이미지를 확인했습니다. 현재 가지고 계신 데이터는 용접 비드의 단면(2D Profile) 정보입니다.
이를 기반으로 전체 면(Surface)을 스캔한 것과 같은 가상 데이터셋 (Synthetic Dataset) 을 생성하려면, 기존 프로파일에 일정한 변화를 주어 Y축 방향으로 확장하는 과정이 필요합니다.
데이터 생성 전략
품질 평가 알고리즘 테스트나 학습용으로 사용할 수 있는 3가지 데이터 생성 전략을 제안해 드립니다.
단순 보간 및 노이즈 추가 방식 (가장 현실적)
실제 용접 비드는 직선처럼 일정하지 않고, 미세하게 흔들리거나 높낮이가 변합니다. 기존 1장의 데이터를 복제하되, 각 라인마다 약간의 무작위성을 부여하는 방법입니다.
- 원본 CSV(X, Z)를 가져옵니다.
- Y축 좌표를 설정합니다 (예: 0.1mm 간격).
- 각 Y 좌표마다 Z값에 가우시안 노이즈 (Gaussian Noise) 를 추가합니다.
- 비드의 중심 위치(X축)를 좌우로 미세하게 Shift(이동) 시킵니다.
장점: 데이터 생성이 매우 빠르며, 센서의 측정 오차까지 시뮬레이션할 수 있습니다.
모핑(Morphing) 기법 활용
만약 '정상 비드' 데이터와 '불량(예: Overlap 또는 Underfill)' 데이터가 각각 1개씩 있다면, 두 데이터 사이를 단계적으로 변화시켜 여러 장을 만들 수 있습니다.
\(Znew=(1−t)⋅Znormal+t⋅Zdefect\)
- Znew: 생성된 새로운 프로파일의 높이 데이터입니다.
- Znormal: 기준이 되는 정상 비드의 높이 데이터입니다.
- Zdefect: 목표로 하는 결함 비드의 높이 데이터입니다.
- t: 보간 계수이며, 0≤t≤1 범위를 가집니다 (t=0이면 정상, t=1이면 결함 상태).
장점: 양품에서 불량으로 넘어가는 과도기적 품질 상태를 연속적으로 생성할 수 있어 판정 임계치(Threshold) 설정에 유리합니다.
사인파(Sine Wave)를 이용한 비드 굴곡 생성
실제 용접은 진행 방향(Y축)으로 물결 모양의 리플 (Ripple) 이 생깁니다. 이를 수식으로 구현합니다.
\(Z(x,y)=Zbase(x)+A⋅sin(2π⋅f⋅y+ϕ)\) Z(x,y): 최종적으로 생성된 3차원 좌표의 높이 값입니다.
- Zbase(x): 원본 CSV에서 가져온 기본 단면 프로파일의 높이입니다.
- A: 사인파의 진폭(Amplitude)으로, 리플의 높낮이 정도를 결정합니다.
- f: 주파수(Frequency)로, 단위 길이당 생성되는 리플의 개수를 결정합니다.
- y: 용접 진행 방향의 좌표입니다.
- ϕ: 위상(Phase)으로, 파형의 시작 지점을 조절합니다.
장점: 시각적으로 매우 실제와 유사한 비드 형상을 얻을 수 있습니다.
Python 샘플 코드
제공해주신 CSV 데이터를 기반으로 Y축 방향 2,000개 라인을 생성하여, 전체 용접면을 구성하는 3D 포인트 클라우드(PLY 파일)를 생성해 드립니다.
실제 용접부의 느낌을 살리기 위해 각 라인마다 미세한 가우시안 노이즈와 비드 위치의 유동성(Wandering) 을 추가하여 가상 데이터를 구성했습니다.
## 이 코드는 원본 데이터 1장을 읽어 Y축으로 2,000번 반복하며 데이터를 확장합니다. 각 좌표는 (X,Y,Z) 형태로 저장됩니다.
import pandas as pd
import numpy as np
# 1. 원본 데이터 로드 (X, Z)
# 사용자 데이터: 컬럼명 없이 x, z 순서로 구성됨
df = pd.read_csv('20260415-butt_bead_profile_sample.csv', names=['x', 'z'])
y_steps = 2000 # 요청하신 2,000개 라인
y_interval = 0.05 # Y축 간격 (mm) - 적절한 밀도를 위해 설정
points = []
print("포인트 생성 중...")
for i in range(y_steps):
y_val = i * y_interval
# 현실성을 위한 무작위 변위 추가
# 1. Z축 노이즈 (센서 노이즈 모사: ±0.005mm)
z_noise = np.random.normal(0, 0.005, len(df))
# 2. X축 미세 흔들림 (용접 진행 시 좌우 유동 모사)
x_shift = np.sin(i * 0.05) * 0.02
for idx, row in df.iterrows():
points.append([row['x'] + x_shift, y_val, row['z'] + z_noise[idx]])
# 2. PLY 파일 형식으로 저장
def save_ply(filename, points):
header = f"""ply
format ascii 1.0
element vertex {len(points)}
property float x
property float y
property float z
end_header
"""
with open(filename, 'w') as f:
f.write(header)
for p in points:
f.write(f"{p[0]:.4f} {p[1]:.4f} {p[2]:.4f}\n")
save_ply('welding_bead_3d.ply', points)
print(f"완료! 총 {len(points)}개의 포인트가 'welding_bead_3d.ply'로 저장되었습니다.")
데이터 생성 상세 설정 (Recipe)
단순 복제가 아닌 품질 평가 알고리즘 테스트에 적합하도록 다음 요소를 반영했습니다.
- Y축 간격 (dy): 2,000개의 라인이 너무 띄엄띄엄 있지 않도록 0.05mm 간격을 기본값으로 설정했습니다 (총 길이 약 100mm).
- 비드 사행 (Wandering): np.sin 함수를 이용해 비드가 아주 미세하게 좌우로 굽이치도록 설정했습니다. 이는 실제 용접 로봇이나 작업자의 손떨림을 모사합니다.
- 표면 거칠기 (Roughness): 가우시안 노이즈를 통해 LVS 센서가 실제 금속 표면을 찍을 때 발생하는 난반사 노이즈를 재현했습니다.
결과 파일
ply로 만들어진 파일을 압축하였다: 20260415-butt_bead_profile_sample-all.zip
다음은 ?
Pointcept:Examples:Weld:LVS 항목 참조.