- 이진 영상은 각 픽셀이 오직 두가지의 값 중 하나만을 가지는 이미지.
- 일반적으로 픽셀 값은 0과 1 또는 0과 255 중 하나의 이진 값을 가지고 있음.
- 일반적으로 물체의 존재와 부재를 나타내는 데 사용되고 있음.
- 정보 손실이 많고, 묘사력이 낮지만 일부 응용프로그램 등에서 물체 감지나 패턴 인식, 이미지 압축과 같은 상황에서 유용하게 활용되고 있음.
앞서 설명된 이진영상 이미지를 1-bit 파일로 압축하여 저장하고, 나타내는 방식을 서술
이진 영상의 경우 영상 픽셀의 값을 0과 1 두가지 값만을 가지고 있기 때문에 1byte씩 입력을 받는 8-bit 이미지와 다르게, 1-bit 즉 1byte당 8개의 pixel 값을 보유하도록 나타낼 수 있다.
예를 들어 1byte가
pixel | 8-bit | 1-bit |
---|---|---|
0 | 00000000 | 0 |
1 | 00000001 | 1 |
2 | 00000000 | 0 |
3 | 00000000 | 0 |
4 | 00000000 | 0 |
5 | 00000001 | 1 |
6 | 00000000 | 0 |
7 | 00000001 | 1 |
라면, 8-bit 파일은 한 픽셀을 표현하는 데, 8개의 Bit를 사용하여 표현하지만 1-bit 파일은 한 픽셀을 표현하는 데 1 bit밖에 사용하지 않아 영상의 용량이 1/8 수준으로 압축되게 된다.
특징
- 이진 영상만 출력이 가능하고, 각 픽셀 역시 0또는 1의 값만 가지고 있다.
- 텍스트나 선 그림, 바코드 등과 같은 간단한 이미지를 출력하는 데 사용된다.
- 용량이 매우 작기 때문에 빠른 속도로 출력물이 형성된다.
lena512.raw
흑백 영상
영상 크기
262KB 임으로 확인할 수 있다.
해당 영상을 이진 영상으로 8-bit Image로 저장하고 Hex editor를 통해 값을 열어보자
작성 코드
# Pillow 라이브러리에서 Image호출 from PIL import Image # 파일 경로 지정 (lena512.raw) file_path = "lena512.raw" # 새로운 RGB형식의 이미지 생성, 이미지 크기는 512,512 img=Image.new("RGB",(512,512)) # pix에 이미지 로드 pix=img.load() # 데이터 파일을 이진법 모드로 open file=open(file_path,'rb') # 이진 데이터를 파일에 쓸 준비 out_file=open("lena512_binary.raw",'wb') # 파일에서 데이터를 읽어오고 data=file.read() # 파일을 닫음 file.close() # 생성된 RGB형식의 이미지의 pixel값에 숫자를 대입하는데 for y in range(512): for x in range(512): # 127을 기준으로 이보다 높으면 255(흰색) 낮으면 0(검정색)으로 표현 tmp=255 if data[y*512+x]>127 else 0 pix[x,y]=(tmp,tmp,tmp) # 255라면 1 저장, else 0 저장 if tmp==255: b=bytes([1]) else: b=bytes([0]) out_file.write(b) # 이미지 출력 img.show() out_file.close()
출력 영상
영상 크기
위와 같이 8-bit 형식으로 이진영상을 저장하게 되면 0 또는 1 (0 또는 255)의 값을 저장하지만 전체적인 bit수 차이는 없기 때문에 용량은 변하지 않는 것을 확인할 수 있음.
저장 형식
와 같이 1 byte 당 1 pixel 값을 대응시켜 표현한 방식이다.
lena512.raw파일의 값을 1bit형식 (+ little Endian 방식) 으로 저장하고 출력해보자.
변환 및 저장 작성 코드
# Pillow 라이브러리에서 Image호출 from PIL import Image # 파일 경로 지정 (lena512.raw) file_path="lena512.raw" # 새로운 RGB형식의 이미지 생성, 이미지 크기는 512,512 img=Image.new("RGB",(512,512)) # pix에 이미지 로드 pix=img.load() # 데이터 파일을 이진법 모드로 open in_file=open(file_path,'rb') # 이진 데이터를 파일에 쓸 준비 out_file=open("lena512_1bit.raw",'wb') # 1바이트크기의 바이너리 데이터 생성 b=bytearray(1) # 512,512 byte를 8로 나누어 값을 하나씩 채워넣는데, for i in range(512*512//8): # 한번에 8byte의 데이터씩 읽어옵니다. data=in_file.read(8) b[0]=0b0000000 #b를 초기화 하고 for j in range(8): # 높은 bit 순대로 낮은 bit에 저장 : Little Endian # ex) data=[0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08] 이라면 1부터 꺼내 마지막 bit에 넣음. # 즉 [0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01]순으로 값을 계산하고 b에 채워넣음 b[0]|=0b00000001<<j if data[j]>127 else 0b00000000 out_file.write(b) #out_file에 값을 쓰고 # 파일을 닫음 in_file.close() out_file.close()
1-bit image 출력 작성 코드
# Pillow 라이브러리에서 Image호출 from PIL import Image # 파일 경로 지정 (lena512_1bit.raw) file_path="lena512_1bit.raw" # 데이터에 이진법 모드로 open with open(file_path,'rb') as file: data=file.read() # 새로운 RGB형식의 512,512크기의 이미지 생성 image=Image.new("RGB",(512,512)) #pix에 이미지 로드 pix=image.load() # index 설정 byte_idx=0 bit_idx=0 # 각 픽셀에 반복하는 데, for y in range(512): for x in range(512): # 이미지의 한 byte당 8개의 pixel에 각각 대입 # [0,1,2,3,4,5,6,7]자리의 수가 [7,6,5,4,3,2,1,0]자리에 올 수 있도록 하나씩 우편으로 이동하며 값을 꺼내와서 bit=(data[byte_idx]>>bit_idx)&0x01 # 해당 비트가 1이라면 255(흰색), 0이라면 0(검정색) tmp=255 if bit==1 else 0 # 이진영상을 표현 pix[x,y]=(tmp,tmp,tmp) # 다음 byte로 넘어감 bit_idx+=1 if bit_idx==8: bit_idx=0 byte_idx+=1 # 이미지 출력 image.show()
출력 영상
영상 크기
로 262KB 크기의 8-bit image에 비해, 1/8 용량의 이미지가 생성된다.
영상 형식
다소 헷갈릴 수 있는 형태를 띄고 있는데, 예를 들어 0x12(19)번 째 값이 31인 byte를 보자!
2진법으로 나타내면 0x31=0b00110001 이다.
즉, 이미지의 8픽셀에 값이 [1,0,0,0,1,1,0,0]으로 채워진다는 것인데, 이는 (512,512)크기의 이미지에서 pix[x,y]=>(144,0)~(151,0)까지 순차적으로 값이 채워진다.