본문 바로가기
Project

[소리 시각화 시키기 1일차] Sound 3D Volume plots in python with go.Volume

by 배애앰이 좋아 2021. 2. 25.
반응형

 

A volume plot with go.Volume shows several partially transparent isosurfaces for volume rendering. The API of go.Volume is close to the one of go.Isosurface. However, whereas isosurface plots show all surfaces with the same opacity, tweaking the opacityscale parameter of go.Volume results in a depth effect and better volume rendering.

 

go.Volume볼륨 렌더링을 위해 부분적으로 투명한 몇 가지 등가 곡면  표시된 볼륨 플롯입니다 . 의 API go.Volume는 중 하나에 가깝습니다 go.Isosurface. 그러나 등가 곡면 플롯 은 동일한 불투명도를 가진 모든 표면을 표시 하는 반면 , 결과 opacityscale매개 변수를 조정하면 go.Volume깊이 효과와 더 나은 볼륨 렌더링이 가능합니다.

 

참고 및 관련 사이트 : plotly.com/python/3d-volume-plots/

 

3D Volume Plots

How to make 3D Volume Plots in Python with Plotly.

plotly.com

 

Simple volume plot with go.Volume

import numpy as np
import plotly.graph_objects as go

# Generate nicely looking random 3D-field
np.random.seed(0)
l = 30
X, Y, Z = np.mgrid[:l, :l, :l]
vol = np.zeros((l, l, l))
pts = (l * np.random.rand(3, 15)).astype(np.int)
vol[tuple(indices for indices in pts)] = 1
from scipy import ndimage
vol = ndimage.gaussian_filter(vol, 4)
vol /= vol.max()

fig = go.Figure(data=go.Volume(
    x=X.flatten(), y=Y.flatten(), z=Z.flatten(),
    value=vol.flatten(),
    isomin=0.2,
    isomax=0.7,
    opacity=0.1,
    surface_count=25,
    ))
fig.update_layout(scene_xaxis_showticklabels=False,
                  scene_yaxis_showticklabels=False,
                  scene_zaxis_showticklabels=False)
fig.show()

 

 

go.volume을 사용하면 위 모습처럼 3d 모습을 효과적으로 표현할 수 있습니다. 이런 점을 이용해서 소리가 사방으로 일정하게 퍼지는 모습을 구현하고자 해보았습니다. 

 

1. 유니티상에서 소리 크기에 대한 데이터 가져오기

 

 

위 그림에서 빨간색 공이 소리라고 했을 때, 빨간 색 화살표처럼 정육면체 모습으로 10x10x10 으로 분할한 다음에 돌아가면서 각 위치에서의 소리의 크기 값을 측정하여 텍스트 파일을 뽑아냈습니다. (데이터 뽑아내기 및 저장)

 

뽑아낸 텍스트 파일

 

위에는 뽑아낸 텍스트 파일로

X_순서 y_순서 z_순서 X_위치좌표 y_ 위치좌표 z_ 위치좌표 사운드_크기_ 

으로 구성되있으며 크기 10x10x10의 정육면체 분할을 측정하여 1000개의 데이터가 들어가 있습니다.

 

2. python 해당 데이터 적용해서 go.Volume 구현

 

< 기본 구현 과정 >

 

(1) 10*10*10 사이즈로 정육면체 분할 지정

 

(2) 미리 뽑아낸 텍스트 파일 읽어 들어와 저장

 

(3) 각 소리 값 구간 별 가중치 추가

 

(4) Valuessound값을 크기 값을 넣어 저장

 

 

이때 3번 과정을 넣어주는 이유는,

 

 

와 같은 이유로 해당 과정을 넣어주게 되었습니다. 또한, 위에 같은 부분은 표면으로 그려지지 않고 값이 0이 되는 부분이 잘리도록 설정되지 않은 코드들이라 그런 부분을 추가로 수정해주었습니다.

 

소리를 바로 시각화 시키기 전에 해당 코드가 제대로 구현하였는지 확인하기 위해 구를 그려보았습니다.

 

구 구현 결과

 

이때 사용한 value 값은 (구 방정식)

 

values = (X - 5)**2 + (Y - 5)**2 + (Z -5)**2

 

사방으로 둘려보았을 경우, 

 

위에 결과 움직이는 영상

 

여기까지 go.Volume 코드가 잘 구현되있는 것을 확인하였으니 본격적으로 소리 시각화를 해보았습니다.

 

현재 사운드 위치 및 환경

 

결과 이미지 1

 

중앙을 중심으로 퍼지는 모습이 나타나기는 하나, 보라색 부분에서 일정하게 퍼진다고 보기 어려운 것 같습니다. 이 문제가 코드의 문제인지 데이터의 문제인지 살펴 봐야할 것 같지만, 아무래도 위 쪽에 구가 잘 나오는 것을 보아서는 현재 데이터를 뽑아내는데 있어서 문제가 있었는 것 같습니다.

 

결과 이미지 2

 

위에 이미지는 결과 이미지 1에서 낮은 소리값을 투명하게 표현, 즉 없앴을 때 모습입니다. 보시다싶이 저희가 원하는 일정하게 퍼지는 구 모습이 나오는 것을 확인할 수 있습니다. 다만, 완전한 구 형체는 아닌 점이 눈여겨 봐야할 거 같습니다. 

 

결과 이미지 3

 

만약 가중치를 다르게 주었으면 어땠을까 해서 저랑 같이 프로젝트를 진행하는 친구가 해 본 테스트 결과입니다. 좀 더 저보다 구가 크고 일정하게 퍼지는게 보이는 게 결과가 잘 나오는 것 같습니다. 다만, 데이터 문제는 똑같이 있었다고 하니 그 부분을 다음에 수정할 필요성이 있는 것 같습니다.

 

현재 사운드 위치 및 환경 - 지형을 적용시킨 환경

 

이번에는 그냥 평면이 아닌 지형을 적용시켰으며, 만약 지형 높이 아래의 소리 값을 측정할 때는 소리 값을 0으로 설정해주었습니다.

 

결과 이미지 4

 

보시다싶이 소리 값이 작은 부분 또는 없는 부분을 없애주니 지형에 해당되는 부분들이 빈 것을 볼 수 있습니다. 또한 지형 위에 올라가있던 소리가 퍼지는 모습 또한, 확인할 수 있습니다.

 

다만, 계속되서 보이는 지형 노이즈라고 할 수 있는 부분들의 정확한 원인을 알 수 있어야할 것 같습니다.

 

< 해당 결과물을 만들 때 쓰인 코드 >

 

import plotly.graph_objects as go
import numpy as np
import matplotlib.pyplot as plt

X, Y, Z = np.mgrid[-1:1:10j, -1:1:10j, -1:1:10j]
data = np.loadtxt("test10.txt", unpack = True, delimiter = " ", skiprows = 1)
maxnum = 0

values =np.sin(np.pi*X) * np.cos(np.pi*Z) * np.sin(np.pi*Y)

k = 0
print("----------------")
print(data[6])
print("----------------")

for i in range(0, 10):
    for n in range(0, 10):
        for p in range(0, 10):
            values[i][n][p] = data[6][k]
            if values[i][n][p] > 0.1 and values[i][n][p] < 1:
                values[i][n][p] += 2
            elif values[i][n][p] > 1 and values[i][n][p] < 8:
                values[i][n][p] += 4
            k += 1
            if k == 999:
                k = 998
            #print(k)

fig = go.Figure(data=go.Volume(
    x=X.flatten(),
    y=Y.flatten(),
    z=Z.flatten(),
    value=values.flatten(),
    isomin=3,
    isomax=10,
    opacity=0.5, # needs to be small to see through all surfaces
    surface_count=10 # needs to be a large number for good volume rendering
    #colorscale='RdBu'
    ))
fig.show()

 

여기까지 소리 시각화시키는 글을 마치면, 다음 글은 오류와 좀 더 업그레이드 시킨 결과와 과정을 들고 오겠습니다. 감사합니다.

 

반응형

댓글