프롤로그
기존에 음성, 영상, 사진 데이터를 매트랩으로 불러오는 과정을 적어두었다.
2024.01.10 - [스펙업/2024 winter-study] - [MATLAB] 매트랩으로 파일 불러오고 저장하기 (동영상, 사진, 음성)
이제 이것을 bit_stream 즉, 00100110110 이런식으로 변환하는 방법을 알아보겠다.
이 비트데이터로 변환된 후 조작을 하는 과정을 C언어 함수를 이용해서 하거나, 직접 만들거나, 무선통신과정에서 상대쪽으로 비트 데이터를 보내고 변조/복조시에 어떠한 일이 발생하는지 파악할 수 있을 것이다.
이미지를 비트 스트림으로 바꾸기
clear variables;
clc;
%%
% 이미지 불러오기
img = imread('./testimg.PNG');
% 이미지 데이터를 uint8 형식으로 변환
img_uint8 = uint8(img);
% 비트 스트림으로 변환
bitStream = typecast(img_uint8(:), 'uint8');
bitStream = reshape(bitStream, 1, [])
% 비트 스트림을 파일로 저장
fileID = fopen('bitstream.bin', 'w');
fwrite(fileID, bitStream, 'uint8');
fclose(fileID);
imread 를 이용하여 testimg.PNG 파일을 불러오고
uint8 또는 uint16, double 같은 것으로 이미지 데이터를 적절한 형식으로 변환한다.
uint8 같은 것들은 매트랩에서 사용되는 데이터 형식으로 unit8은 8비트, uint16은 16비트의 부호 없는 정수로 나타낸다.
double 은 64비트 메모리를 사용하여 숫자를 저장한다. 52비틑 유효숫자, 11비트는 지수, 1비트는 부호를 나타낸다.
8 < 16 < double 순으로 더 정밀하고 세세하게 데이터를 만질 수가 있다.
하지만 우리는 그냥 uint8 수준에서 하자.
다음은 typecast인데
Y = typecast(X, type)
위와 같이 사용한다. 변수의 데이터타입을 변경하지 않고 메모리에 저장된 형식만을 변경한다. 기존 데이터의 바이트 표현을 유지하면서 다른 데이터 타입으로 해석하도록 해준다. 즉, 데이터 자체는 변환되지 않고 그 데이터가 해석되는 방식만 바뀐다.
비트스트림으로 바뀐 모습이다.
현재 n X 1 차원 행렬로 되어있는데, 1Xn 차원으로 바꿔주기 위해 reshape를 사용한다.
A = reshape(A, 1, []);
아니면
A = A.';
이렇게 사용해줘도 되긴한다.
최종적으로는
1 X 207603 의 크기로 잘 완성이 되었다.
여기서 궁금해서 추가적으로 찾아본건데
위의 사진을 img 로 불러왔을 때 왜 297X233X3 으로 되어있나 궁금했는데 그 이유는..
처음 297 : 이미지의 세로 크기를 픽셀 단위로 나타내기
233 : 이미지의 가로 크기를 픽셀 단위로
3: 각 필셀에 대한 컬러 채널의 수. RGB 세 가지의 색상의 채널의 강도이다. 0 ~ 255 사이의 수를 가지고 있다.
2차원 297*233 으로만 간다면 흑백 이미지인데 3차원으로 바꿔서 RGB 색까지 넣어준 것이다.
아무튼 이렇게 완성된 비트스트림을 bin(바이너리 파일)로 저장하는 법은..
fileID = fopen('bitstream.bin', 'w');
fwrite(fileID, bitStream, 'uint8');
fclose(fileID);
이렇게 하면 된다.
fopen(파일명, w) 에서 w는 쓰기 모드를 의미한다. fwirte에서 맨 뒤 인자는 형식을 지정한다.
음성 파일을 비트스트림으로 바꾸기
저번 글을 토대로 음성 데이터를 불러왔을 때
[audioData, sampleRate] = audioread('./testvoice.m4a');
이렇게 audioData는 216063 x 2 double 로 가져와진다. 즉 2차원 배열인데,
216030은 오디오 파일의 총 샘플 수, 샘플은 디지털 오디오의 기본 단위로, 연속된 아날로그 신호를 디지털 형태로 변환할 때 일정 시간 간격으로 측정한 아날로그 신호의 강도이다. 이 강도는 사운드의 높낮이(주파수)나 불륨(진폭)을 수치적으로 표현한 것이다.
X2 이 것은 오디오 파일이 스테레오인 경우 각 샘플에 대해 두 개의 채널(왼쪽과 오른쪽 스피커)가 있다는 것을 나타낸다. 두 신호의 조합으로 입체감 있는 사운드를 생성한다.
double 은 데이터 형식을 의미한다.
즉 다시 말하면 첫번째 차원은 시간축을, 두 번째 차원은 스테레오 채널을 의미한다. 이 스테레오 채널은 왼쪽, 오른쪽 채널의 샘플값이다.
double형식일 때는 대부분의 값이 -1.0~1.0 사이에 위치하고 있고, 이것을 일차원 으로 바꿔줘야한다.
% 오디오 파일을 불러옵니다.
[audioData, sampleRate] = audioread('testvoice.m4a');
% double 형식의 데이터를 int16 범위로 스케일링
% double 형식의 범위는 -1.0 ~ 1.0 이며,
% int16 형식의 범위는 -32768 ~ 32767이기에, 32767을 곱해준다.
scaledAudioData = audioData * 32767;
% double 형식에서 int16 형식으로 변환
int16_audioData = int16(scaledAudioData);
% 스테레오 데이터이므로 모든 데이터를 한 줄로 펼침.
bitStream = typecast(int16_audioData(:), 'uint8');
% 비트 스트림을 파일로 저장
fileID = fopen('audio_bitstream.bin', 'w');
fwrite(fileID, bitStream, 'uint8');
fclose(fileID);
우선 double 형식은 -1~1 사이기에, int16 형식인 -32768 ~ 32767 로 바꿔주기 위해 audioData 값에 32767 을 곱해준다.
그 후로, int16형식으로 변환 시켜주면
소수점으로 있던 것이
정수로 바뀐다.
이걸 아까 사진처럼 한 줄로 바꿔주는 작업
% 스테레오 데이터이므로 모든 데이터를 한 줄로 펼침.
bitStream = typecast(int16_audioData(:), 'uint8');
을 하는 것이다.
이 typecast 가 필요한 이유는 부동소수점에서 정수로 내려가면서 데이터 손실이 발생할 수 있는데, 데이터 손실을 방지하기 위한 작업이라고 생각하면 된다. 데이터를 다른 데이터 타입으로 변환할 때 자동으로 수행되지 않고, 프로그ㅜ래머가 명시적으로 지정하는 작업이 필요하다.
아무튼 최종적으로는
이렇게 완성되었다.
동영상을 비트스트림으로 바꾸기
비디오 데이터는 한 프레임씩 짤라서 가져오기 때문에 일단 데이터 크기가 매우 클 것이다
clear variablesl
clc;
% 비디오 파일을 읽기
videoFile = VideoReader('./testvideo.mp4');
% 비트스트림 파일 열기
bitstreamFile = fopen('output_bitstream.bin', 'wb');
% 각 프레임을 처리
while hasFrame(videoFile)
% 비디오 프레임을 읽기
frame = readFrame(videoFile);
% 프레임을 비트스트림으로 변환하여 파일에 쓰기
fwrite(bitstreamFile, frame(:), 'uint8');
end
% 파일을 닫기
fclose(bitstreamFile);
fopen 으로 wb 로 바이너리 형식으로 쓴다는 것으로 열고
프레임을 처리하기 위해서 while hasFrame , 이걸 비트스트림 형식으로 변환하여 파일에 쓴다.
비상;;
6초짜리 영상인데 20분동안 안 씌워져서 이건 일단 넘어가야겠다.
에필로그
이상이다.
'스펙업 > 2024 winter-study' 카테고리의 다른 글
[MATLAB] 매트랩에서 파이썬 코드 실행하기 (AES) (0) | 2024.01.19 |
---|---|
[MATLAB] 매트랩에서 파이썬 코드 실행하기 (3DES) (0) | 2024.01.18 |
[MATLAB] 매트랩에서 C언어 함수 사용하기 (2) | 2024.01.12 |
[MATLAB] 매트랩으로 파일 불러오고 저장하기 (동영상, 사진, 음성) (0) | 2024.01.10 |