C && C++/BMP

BMP파일 다루기(C++)/ C++ BMP 이미지 변형 수정 하기.

힘법사 2020. 10. 11. 22:33
728x90

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을 누르면 초                 록색으로 옷색이 바뀌게 된다. 이 결과는 역시 저장된다.

먼저 결과물들을 보겠습니다.

그림1. 프로그램 실행시 디버그 콘솔의 모습
그림2. 원본 사진(original)
그림3. 좌로부터 흑백 변환, 파란색 초록색 게열로 변환, 파란색 빨간색 계열로 변환

동작된 결과 원본사진에서 색이 잘 변환되어 원하는 사진들을 얻은 것을 확인할 수 있습니다. 색이 변했지만 옷의 주름까지 잘 표현됬네요^^ 원리는 다음과 같습니다.

 흑백 사진으로 변환 원리 :

 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;
}

다음 생각해봐야할 과제 : 

옷색을 바꾼다던가 흑백으로 바꾸는데 성공했지만, 만약 위의 사진에서 옷 색이 검은색이면 어떻게 할 수 있을까? 고민해 봐야합니다. 지금과 같이 색을 탐지하는 방식으로는 머리색과 눈동자 색마저 바뀝니다. 이런 방법에 대한 앞으로의 연구를 해보겠습니.

728x90

'C && C++ > BMP' 카테고리의 다른 글

그림판을 이용한 .png 파일 .bmp로 바꾸기  (0) 2020.10.12