1. bmp file의 포멧
bmp file은 사진의 싸이즈 정보(폭, 높이)와 pixel foramt option을 포함하고 있습니다.
본 게시물에서 Pixel format은 24bits(3bytes. RGB interlaced)를 이용할 예정입니다.
※ 3bytes의 RGB interlaced란 한 픽셀에 R(1byte)G(1byte)B(1byte)형식의 데이터를 통해 색을 나타내는 것이다. 색은 0-255 level까지 선택이 가능하다.
2.원하는 색을 탐지하여 다른색으로 바꾸는 프로그램(Detecting color and changing to another one)
설명 : 원본 이미지 파일(.bmp)을 로드하여 그 이미지를 흑백으로 변환하거나 옷색을 전환하고 이를 세이브하는 기능을 수행한다.
동작 설명 : 프로그램을 실행 후 0을 누르면 흑백사진이 생성되어 저장된다.
1을 누르면 옷색 바꾸기 기능에 들어가고 여기서 0을 넣으면 빨간색으로 옷색이 바뀌게 되고 1을 누르면 초 록색으로 옷색이 바뀌게 된다. 이 결과는 역시 저장된다.
먼저 결과물들을 보겠습니다.
동작된 결과 원본사진에서 색이 잘 변환되어 원하는 사진들을 얻은 것을 확인할 수 있습니다. 색이 변했지만 옷의 주름까지 잘 표현됬네요^^ 원리는 다음과 같습니다.
흑백 사진으로 변환 원리 :
bmp 파일은 3바이트가 한 픽셀을 이룬다고 앞서 설명하였습니다. 각 픽셀의 3바이트의 level들을 알아낸 후, RGB 세 level을 평균을 취한 값으로 새 bmp파일을 생성합니다. 이 방식을 적용하면 RGB 값이 동일하므로, 흑백사진이 생성됩니다. 또한, 세 레벨의 평균을 취해준 효과 덕에 명암까지, 살려낼 수 있습니다.
파란색 계열의 색에만 한정해서 초록색 또는 빨간색계열로 색 변환 :
bmp는 B G R 순서대로 pixel에 저장되서 색을 표현합니다. 파란색 계열의 색을 탐지해야하는 상황에서 우리가 생각해 볼 수 있는 것은 다음과 같습니다.
1. 파란색 계열의 색 또한 B G R 값을 모두 가지고 있다.
2. 하지만 파란색이기 때문에 B 값이 G 그리고 R 값에 비해 유의미하게 클 것이다.
이 두가지 사실을 이용해서 B의 level의 두배 되는 값이 G와 R을 더한 레벨보다 크다면 그 색의 level을 조정해 주었습니다.
(코드에서는 2 * B > G * 1.5 + R 일 때)
조정 방법은 다음과 같습니다.
1.타겟 색깔(변환하고 싶은 색)의 level을 기존B 값의 level로 설정했다.
2. 타겟 색깔이 아닌 나머지 두 색의 level은 B 값을 제외한 임의의 색의 level에 0.5를 곱해서 대입 해주었다.(이렇게 하면 나머지 색은 약해지게 됩니다.)
코드 :
#include <iostream>
#include "bmpOld.h"
using namespace std;
int main() {
int x, y;
unsigned char* bmp = ReadBmp("img.bmp", &x, &y);
unsigned char* bmpn = new unsigned char[x * y * 3];
int processor;
cout << x << ", " << y << endl;
cout << "해당 이미지로 어떤 동작을 수행하시겠습니까?" << endl << "흑백변환 : 0" << endl << "옷색 바꾸기 : 1"<< endl;
int function;
cin >> function;
if (function == 0) {
for (int i = 0; i < x * y * 3; i += 3) {
processor = round((bmp[i] + bmp[i + 1] + bmp[i + 2]) / 3);
bmpn[i] = processor;
bmpn[i + 1] = processor;
bmpn[i + 2] = processor;
}
SaveBmp("bw_img.bmp", bmpn, x, y);
}
else if (function == 1) {
cout << "무슨 색으로 맞추시겠습니까?" << endl << "RED = 0, Green = 1" << endl;
int color;
cin >> color;
for (int i = 0; i < x * y * 3; i += 3) {
bmpn[i] = bmp[i]; // B
bmpn[i + 1] = bmp[i + 1]; // G
bmpn[i + 2] = bmp[i + 2]; // R
if (color == 0) {
if (2 * bmp[i] > (bmp[i + 1] * 1.5 + bmp[i + 2])) {
bmpn[i] = round(bmp[i + 2] / 2); // B
bmpn[i + 1] = round(bmp[i + 1] /2); // G
bmpn[i + 2] = bmp[i]; // R
}
}
else if (color == 1) {
if (bmp[i] + bmp[i+1] > (bmp[i + 1] * 1.5 + bmp[i + 2])) {
bmpn[i] = round(bmp[i] / 2); // B
bmpn[i + 1] = bmp[i + 2]; // G
bmpn[i + 2] = round(bmp[i + 1] / 2); // R
}
}
else {
cout << "잘못된 색상 입력입니다." << endl;
return -101;
}
}
if (color == 0) {
SaveBmp("color_change_to_red_img.bmp", bmpn, x, y);
}
else if (color == 1) {
SaveBmp("color_change_to_green_img.bmp", bmpn, x, y);
}
}
else {
cout << "잘못된 입력입니다." << endl;
return -100;
}
return 0;
}
다음 생각해봐야할 과제 :
옷색을 바꾼다던가 흑백으로 바꾸는데 성공했지만, 만약 위의 사진에서 옷 색이 검은색이면 어떻게 할 수 있을까? 고민해 봐야합니다. 지금과 같이 색을 탐지하는 방식으로는 머리색과 눈동자 색마저 바뀝니다. 이런 방법에 대한 앞으로의 연구를 해보겠습니.
'C && C++ > BMP' 카테고리의 다른 글
그림판을 이용한 .png 파일 .bmp로 바꾸기 (0) | 2020.10.12 |
---|