워터마크 넣기
4회 만에 처음으로 책(Visual C++ 영상 처리 프로그래밍)에는 없는 내용을 다뤄본다.
이미지에 워터마크 넣기! 최하위 비트에 0이라는 숫자 이미지를 넣어볼 것이다. 원본 이미지는 3회에서 사용한 이미지인 camera.bmp를 그대로 사용할 것이다. 해당 이미지 최하위 비트에 원하는 정보를 넣어보자.
원본 이미지와 최하위 비트에 원하는 정보를 넣은 결과 이미지는 육안으로 봤을 때 거의 차이가 없다. 도저히 구별할 수 없는 수준이다.
실제로 어떤 작업을 수행했는지 코드를 살펴보자.
먼저 최하위 비트에 추가된 이미지는 zero.bmp라는 파일이다. 임시로 그림판으로 만든 이미지이다. camera.bmp 파일을 하나 복사한 후에 그림판으로 열어서 기존 이미지를 지우고 대충 그리면 된다. 그리기 귀찮으면 다음의 첨부파일을 다운로드하여서 사용하자.
if zero_img[i, j] == 0 이란 의미는 이미지의 그레이스케일 값이 0인 부분, 즉 zero.bmp에서 검은색 부분을 의미한다.
이때 최하위 비트를 0으로 만들어 준다. 왜냐하면 비트 평면 분할은 이전 포스팅에서 사용한 것을 그대로 사용할 것이기 때문이다. 간단히 다시 설명하면 각 비트가 0이면 해당 픽셀을 0(검은색), 1이면 해당 픽셀을 255(흰색)로 설정해주는 방식이었다. 그렇기 때문에 검은색의 0이란 모양을 그대로 옮기기 위해서는 그레이스케일 값이 0일 때 최하위 비트를 0으로 설정해야 한다.
원본 이미지 정보를 담고 있는 Mat 타입인 camera_img의 최하위 비트만 0으로 변경하기 위해서 camera_img[i, j] & 254로 and 연산을 한다. 254는 2진수로 11111110이기 때문이다. 따라서 상위 7비트는 원본 그대로 보존될 것이고 최하위 비트는 모두 0으로 바뀐다.
반대로 zero.bmp에서 배경 부분은 흰색으로 처리하면 된다. 따라서 최하위 비트를 1로 변경해야 한다. 그러기 위해서는 원본 이미지의 그레이스케일 값이 0이 아닐 때 out_img[i, j] = camera_img[i, j] | 1과 같이 하면 된다. 1은 2진수로 00000001이고 or 연산을 했기 때문에 상위 7비트는 원본 그대로 보존될 것이고 최하위 비트는 모두 1로 변경된다.
import matplotlib.pyplot as plt
import cv2
def draw_image(original_img, result_img, title, sub_title1, sub_title2):
fig = plt.figure()
fig.suptitle(title)
ax = fig.add_subplot(1, 2, 1)
ax.imshow(original_img, cmap=plt.cm.gray)
ax.set_title(sub_title1)
ax = fig.add_subplot(1, 2, 2)
ax.imshow(result_img, cmap=plt.cm.gray)
ax.set_title(sub_title2)
plt.show()
def set_watermark():
camera_img_path = "img\camera.bmp"
zero_img_path = "img\zero.bmp"
camera_img = cv2.imread(camera_img_path, cv2.IMREAD_GRAYSCALE)
zero_img = cv2.imread(zero_img_path, cv2.IMREAD_GRAYSCALE)
out_img = camera_img.copy()
row, col = camera_img.shape
for i in range(0, row):
for j in range(0, col):
if zero_img[i, j] == 0:
out_img[i, j] = camera_img[i, j] & 254
else:
out_img[i, j] = camera_img[i, j] | 1
draw_image(camera_img, out_img, "Set Watermark", "Original Image", "Result Image")
cv2.imwrite("camera_watermark.bmp", out_img)
set_watermark()
여기까지 하면 camera_watermark.bmp라는 결과 이미지가 만들어진다.
해당 이미지를 비트 평면 분할하여 실제로 최하위 비트에 제대로 정보가 쓰였는지 확인해 보자.
결과를 보면 최하위 비트에 zero.bmp를 기반으로 추가한 정보가 제대로 들어가 있다.
ref.)
이미지 출처 : https://github.com/gilbutITbook/006796/blob/master/images/ch07/camera.bmp