컬러이미지 (Color image)를 R, G, B 요소로 분리하기


컬리이미지의 각 픽셀은 3개  색채널 (red, green, blue)로 구성되어 있다.

따라서 이미지에서 각 채널별 요소를 분리해 낼 수 있다.


아래와 같은 컬러이미지가 있다고 하자.

 

Red 채널만 뽑아낸 결과

위의 영상에서 G와 B는 무시하고, R에 해당하는 값만 뽑아낸 결과는

아래와 같다.

왼쪽 잔의 음료수 색이 빨간 색에 가까웠기 때문에,

Red만 뽑아낸 영상에서는 해당 부분이 하얗게 나타난다.

그리고 원래 하얀색이었던 부분은 R, G, B값이 모두 컸기 때문에

Red만 뽑아낸 영상에서도 하얗게 나타난다.

Green 채널만 뽑아낸 결과

Blue 채널만 뽑아낸 결과


함수 split( )


OpenCV 라이브러리에서는 컬러이미지를 

각 채널별로 분리해내는 함수 split( )을 제공한다.

이것을 이용하여 구현한 프로그램은 아래와 같다.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <opencv2/opencv.hpp>
#include <iostream>


using namespace cv;
using namespace std;

int main(int argc, char** argv)
{

	if (argc != 2)
	{
		cout << " Provide image name to read" << endl;
		return -1;
	}

	Mat inputImg;

	inputImg = imread(argv[1], CV_LOAD_IMAGE_COLOR);

	vector<Mat> bgr_images(3);
	split(inputImg, bgr_images);

	namedWindow("Original", CV_WINDOW_AUTOSIZE);
	namedWindow("Blue", CV_WINDOW_AUTOSIZE);
	namedWindow("Green", CV_WINDOW_AUTOSIZE);
	namedWindow("Red", CV_WINDOW_AUTOSIZE);

	moveWindow("Original", 100, 100);
	moveWindow("Blue", 120, 120);
	moveWindow("Green", 140, 140);
	moveWindow("Red", 160, 160);

	imshow("Original", inputImg);
	imshow("Blue", bgr_images[0]);
	imshow("Green", bgr_images[1]);
	imshow("Red", bgr_images[2]);


	waitKey(0);

	return 0;
}


line 21-22:

	vector<Mat> bgr_images(3);
	split(inputImg, bgr_images);

inputImg는 RGB 3개의 채널을 가진 컬러이미지이다.

이를 R,G,B로 분리해 내기 위해서는,

각 채널별로 저장할 공간을 만들어야 한다.

이를 위해, Mat의 vector인 bgr_images를 만든다.

이것은 크기 3인 배열이라고 생각하면 된다.


함수 split( )호출은 inputImg를 R,G,B로 분리한다.

이 때, 

bgr_images[0]은 Blue

bgr_images[1]은 Green

bgr_images[2]는 Red 채널에 해당하게된다.

RGB 순서가 거꾸로 저장된다고 이해하면 쉽다.


line 29-37:
	moveWindow("Original", 100, 100);
	moveWindow("Blue", 120, 120);
	moveWindow("Green", 140, 140);
	moveWindow("Red", 160, 160);

	imshow("Original", inputImg);
	imshow("Blue", bgr_images[0]);
	imshow("Green", bgr_images[1]);
	imshow("Red", bgr_images[2]);

4개의 이미지 창을 만들어

원래 이미지와 함께, R, G, B 분리 결과를 보여준다.

함수 moveWindow( )는 해당 윈도우의 표시위치를 지정할 수 있도록 한다.


반응형
LIST




반전 이미지 만들기 (Make inverted image)


컬러 이미지는 하나의 픽셀마다 

빨간색, 녹색, 청색 (Red, green, blue)의 3가지 정보를 가지고 있다.

각각의 색깔 정보를 전문용어로 채널(channel)이라고 한다.


일반적으로 각 채널은 8 bit을 사용하므로

256 가지 의 색을 표시할 수 있다.

즉, 0부터 255까지의 값을 가질 수 있다.


이론적으로 보자면,

각 채널이 256가지의 색을 표현하기 때문에,

3개 채널을 모두 고려하면 256 * 256 *256 가지의 색깔 표현이 가능한 것이다.


반전 이미지 (inverted image)는 

각 채널의 값 v를 255-v로 대체하는 것을 말한다.

쉽게 말하면, 0을 255로 바꾸는 것이다.

직관적으로 이해하자면, 검정색이 흰색이 되는 것이다.

이를 구현한 것이 아래 코드이다.


void InvertColor(Mat& input_img, Mat& inverted_img)

{

   CV_Assert(input_img.type() == CV_8UC3);

   inverted_img = input_img.clone();


   for (int row = 0; row < input_img.rows; row++)

   {

      for (int col = 0; col < input_img.cols; col++)

      {

         for (int ch = 0; ch < input_img.channels(); ch++)

{

   inverted_img.at<Vec3b>(row, col)[ch] = 255 - inverted_img.at<Vec3b>(row, col)[ch];

 }

      }

   }

}


우선, 인수로 주어지는 input_img가 3개 채널을 갖는 컬러영상이고,

각 채널이 8bit인지를 확인한다.

그리고 나서는, 모든 픽셀에 대해 (2개의 바깥 for-loop 부분), 

각 채널값을 꺼내서 반전시켜서 다시 넣는다. (가장 안쪽의 for-loop 부분)


각 픽셀의 3개 채널값을 한 번에 읽는 방법은 다음과 같다.

inverted_img.at<Vec3b>(row, col)

이후에 개별 채널값은 배열 인덱스를 이용하여 읽어내면 된다.


inverted_img.at<Vec3b>(row, col)[ch]


웹캠으로부터 들어오는 컬러 영상을 

함수 InvertColor( )를 이용하여 반전시키는 프로그램은 아래와 같다.

코드의 함수 onmouse( )와 헤더, 매크로 선언 부분은 이전 포스트를 참조하면 되겠다.



프로그램 수행결과는 아래와 같이, 반전을 하기 전의 원래 영상과 반전 영상이다.


<< 원래영상>>


<< 반전 영상>>







반응형
LIST




웹캠(webcam) 영상을 Grey로 출력하기


웹캠으로부터 들어오는 영상을 회색영상으로 변환하여 출력하는 프로그램이다.

아래 그림에서 위의 것은 webcam에서 들어오는 원래 컬러영상이고,

아래 것은 이를 grey로 바꾼 것이다. (사실 grey변환 외에도 quantisation을 수행한 것으로, 이에 대해서

밑에서 좀 더 자세히 설명한다.)



line 15

USB로 연결된 웹캠을 이용하려면 OpenCV에서 제공하는

VideoCapture 객체를 사용하면 편리하다.

각 카메라마다 ID를 붙이는데, 기본으로 붙어있는 카메라는 0, USB로 연결한 웹캠은 1 정도 된다.

이건 ID를 바꿔가면서 테스트해보면 된다.


line 26

마우스 클릭을 처리하기 위해서, 클릭 이벤트시 수행할 함수를 설정하는 부분이다.

"cam"은 마우스 클릭을 감지할 윈도우이고,

onmouse는 수행할 함수이고, 

&greyImg는 이 함수에 넘겨줄 인수이다.


line 30

웹캠에서 들어오는 영상을 frame에 저장한다.

OpenCV에서 웬만한 부분은 다 처리하기 때문에, read 함수만 호출하면 된다.


line 32

컬러영상을 담고 있는 frame을 회색조 (grey) 영상인 greyImg로 변경한다.

이 때 OpenCV에서 제공하는 함수 cvtColor ( )를 이용한다.


line 33

Quantisation하는 부분이다. Grey영상의 픽셀들은 256 단계를 갖는데,

이를 지정하는 단계수( 2의 3승)로 바꾸는 과정이다.

여기서는 8 (= 2^3)단계로 바꾼다.


마우스 이벤트 핸들러 함수

왼쪽 버튼이 눌렸을 때, 

그 위치에서의 픽셀값과 위치를 출력하는 함수이다.


Quantisation 함수

256단계의 grey 이미지를 2^num_bits 단계로 바꾸는 단계이다.

만약 num_bits = 1이면, 2단계, 즉 흑백 영상으로 표시한다.

num_bits = 1일 경우에, 흑백으로 quantisation된 예이다.


반응형
LIST



Ragged 배열(Array)


Ragged의 의미

'너덜너덜해진', 

'옷이 누더기가 된',

'해진' 이라는 뜻을 갖는다.



그래서, ragged flag라고 하는 것은

위의 그림처럼 끝이 다 해진 깃발을 말한다.


Ragged 배열(array)의 의미

2차원 배열을 생각해 보면,

각 행마다 열의 개수가 모두 똑같다.

Ragged array는 각 행마다 열의 개수가 다른 배열을 의미한다.


아래 그림을 보자.

왼쪽에는 일반 2차원배열이 있다.

3개의 행으로 이루어져 있고, 각 행마다 모두 3개씩의 열을 갖는다.

반면에,

오른쪽을 보면 2차원 배열이긴 한데, 모양새가 예사롭지 않다.

우선 3개의 행이 있으되,

0번 행은 2개의 열,

1번 행은 3개의 열,

2번 행은 4개의 열을 갖는다.

이런 것을 ragged array라고 한다.



Ragged 배열의 생성


Ragged 배열은 각 행마다 열의 개수가 다르기 때문에,

일반적인 이차원 배열처럼 만들 수는 없다.

대신, 각 행마다 필요한 열의 개수만큼 만들어 넣어야 한다.

예를 들어, 위의 그림에 나온 ragged 배열을 만드는 프로그램은 아래와 같다.



line 8

행의 개수만 3으로 정해졌기 때문에, 열의 개수는 공백으로 둔 채 2차원 배열을 만든다.

line 10

0번 행에는 2개의 공간을 만들기 위해 크기 2인 일차원 배열을 만들어 넣는다.

line 11, 12

1번 행과 2번 행에 각각 크기 3과 4인 일차원 배열을 만들어 넣는다.

line 14-16

만들어지 공간에 값을 넣어본다.


3차원 Ragged 배열


3차원 ragged의 경우에는 머리 속에 금방 떠올리기가 쉽진않다.

우선 아래 프로그램은 ragged 배열을 만드는 예를 보여준다.

line 8

전체 3개의 그룹이 있고, 그룹 안을 어떻게 나누어 쓸 것인가는 그룹별로 결정할 것이므로 나머지는 공백으로 둔다.

line 10-12

그룹안에 서브그룹을 만드는 것이다. 이것은 2차원 배열로 한다. 0번 그룹은 2개의 서브그룹을 만들고, 각 서브그룹마다 공간의 개수가 다르므로 공백으로 둔다.

line 14-22

가장 안쪽에 실제 데이터를 저장하는 공간을 만드는 것이다.


위의 코드 수행에 따른 ragged배열 생성을

그림으로 그려보면 다음과 같다.

실제 데이터가 저장되는 공간은 굵은 점으로 표시하였다. 


반응형
LIST


Visual Studio의 scanf 문제


Visual studio 2015를 사용할 때,

(2013 버전도 마찬가지지만,)

다음과 같은 프로그램을 빌드한다고 하자.

scanf 함수를 이용해서 

숫자를 입력받고,

출력하는 프로그램이다.

그런데,

...

...

빌드하면 다음과 같은

warning메시지가 뜬다.



문자 그대로 해석을 하면


경고 C4996: 'scanf': 이 함수 또는 변수는 사용하면 위험할 수 있습니다. 

이것 대신에 scanf_s 함수를 사용하기를 바랍니다. 

이 경고 메시지를 끄시려면, _CRT_SECURE_NO_WARNINGS를 사용하고,

이에 대한 자세한 설명은 도움말을 찾아보세요.


아시겠지요..

scanf는 해킹의 우려 때문에 위험할 수도 있습니다.

그래서,

두 가지 해결책을 제시하고 있지요.

첫 번째는 scanf 대신에 scanf_s를 쓰면 되는 것이고,

이것이 싫다면,

프로그램 시작부분에 아래를 쓰면 된다.

#define  _CRT_SECURE_NO_WARNINGS 


이렇게 말이다.

이러면 더 이상 경고메시지가 나오지 않는다.

그런데요, 

제 프로그램 scanf썼는데 해킹당하면 어떻게 해요?


해커들도 프로그램 가려서 한다.

갸들도 보는 눈이 있단다.


반응형
LIST

동전 던지기
동전이 있다. 앞면과 뒷면이 있다.
던져서 동전이 똑바로 서는 경우도 있겠지만, 이런 경우는 없다고 가정하자.
그러면 앞면이 나오거나, 뒷면만 나올것이다.
던져서 앞면이 나올 확률은 1/2이다.
뒷면이 나올 확률은 전체 확률 1에서 앞면이 나올 확률을 뺀 것, 즉 1 - 1/2 = 1/2 이다.

앞면이 나오는 횟수
동전을 5번 연속해서 던져본다.
앞면이 1번 나오면, 나머지는 당연히 뒷면이 4개 나올 것이다.
반대로 앞면이 4번 나오면, 뒷면은 1번 나올 것이다.
이제, 동전의 앞면이 몇 번 나올지 그 확률을 계산해 보자.

ㅇ 극단적인 경우
동전을 10번 던진다고 하자.
앞면이 10번 다 나오거나, 0번, 즉 한 번도 나오지 않는 경우도 있을까?
이런 일은 극히 드물게 일어나지만, 일어나는 경우도 있다.
이는 마치, 내가 로또를 샀는데, 당첨되는 일과 마찬가지다.
극히 드물게 일어나지만, 어쨌든 일어난다.

ㅇ 동전 앞면이 나오는 경우
          동전을 또 10번 던진다고 하자.
10번 다 앞면이 나오는 경우와 5번만 앞면이 나오는 경우를 생각해보자.
상식적으로 생각했을 때, 5번만 앞면이 나오는 경우가 훨씬 발생할 가능성이 많을 것이다.
5번이 나오는 경우를 생각해 보자.
가장 쉽게, 던지자마자, 5번 연속해서 앞면이 나오고, 그 다음 5번은 줄기차게 뒷 면만 나오는 경우가 있다.
또는 그 반대의 경우 뒷면만 5번 연속해서 나오고, 그 다음은 쭉 앞면.
일반적으로는 앞면과 뒷면이 막 섞여서 나오는 경우가 대부분일 것이다.

ㅇ 앞면이 나올 확률
동전을 1번만 던진다고 하자.
앞면이 1번 나올 확률은 얼마인가? 생각할 필요도 없이 1/2이다.
동전을 2번 던진다고 하자.
앞면이 1번 나올 확률은 얼마인가? 이건 좀 생각해 봐야한다.
우선 나타날 수 있는 모든 경우의 수를 생각해 보자.
총 4가지 경우를 생각할 수 있다.
앞앞, 앞뒤, 뒤앞, 뒤뒤
이 중에서 1번 앞면이 나올 확률은 2가지다.
앞뒤, 뒤앞.
따라서 2번 던져, 1번 앞면이 나올 확률은 2/4 = 1/2이다.
앞면이 0번 나올 확률은 얼마인가?
1/4이다.
앞면이 2번 나올 확률은 얼마인가?
1/4이다.
동전을 3번 던진다고 하자.
앞앞앞, 앞앞뒤, 앞뒤앞, 앞뒤뒤, 뒤앞앞, 뒤앞위, 뒤뒤앞, 뒤뒤뒤
앞면이 1번 나올 확률은 얼마인가?
앞면 1번은 3번 나온다. 확률은 3/8

ㅇ 쉽게 계산해보자. 앞면이 나올 확률
동전을 10번 던져보자.
이 중에서 앞면이 5번 나오는 경우를 생각해보자.
앞면이 5번이 나오는데, 처음에 연속해서 나올 확률은 얼마인가?
(1/2)(1/2)(1/2)(1/2)(1/2)(1-1/2)(1-1/2)(1-1/2)(1-1/2)(1-1/2)
나중에 몰아서 연속해서 나올 확률은 얼마인가?
(1-1/2)(1-1/2)(1-1/2)(1-1/2)(1-1/2)(1/2)(1/2)(1/2)(1/2)(1/2)
순서는 상관없이,
10번중 앞면이 5번 나오는 경우는 모두 몇 번 일어나는가?
조합 (combination)으로 계산하면 된다.
10C5 = 10!/ 5! (10-5)!
따라서 확률은 10C5 * (1/2)^10

ㅇ Binomial distribution
이러한 동전던지기와 관련된 확률을 계산하는 것이다.
Bin (n, p).
n은 시도하는 전체 횟수
p는 원하는 일이 발생할 확률
원하는 일이 n번중 x번 발생할 확률 계산은
nCx * p^x * (1-p)^(n-x)

ㅇ 동전을 20번 던졌을 때, 앞면이 나올 확률 그래프.
x축은 앞면이 나올 횟수
y축은 해당하는 확률
20번 중 10번 앞면이 나올 확률이 가장 크다.
`

ㅇ 던지는 회수가 늘어날 때, 앞면이 10번 나올 확률 그래프.
동전던지는 총 회수에 따른 확률
x축은 동전던지는 회수
총20번 던졌을 때, 10번 앞면이 나올 확률이 제일 높다.


ㅇ 불량동전 던지기
불량동전이라서 앞면이 나올 확률이 1/2이 아니다.
20번 던졌을 때, 10번 앞면이 나올 확률을 계산하자.
x축은 동전 앞면이 나올 확률.
재미있는 사실. 앞면이 나올 확률이 1.0이 되면, 20번 중에 앞면이 10번 나올 확률은 0이 된다.
이유는, 20번 다 앞면이 나오기 때문에.











 

반응형
LIST

 디코딩 검증



반응형
LIST

 디코딩 구현 Part 3



반응형
LIST

디코딩 구현 Part 2



반응형
LIST

디코딩 구현 Part 1



반응형
LIST

디코딩 코드 리뷰



반응형
LIST

디코딩 이론



반응형
LIST

비트 인코딩 테스트 (Bit Encoding Test)



반응형
LIST

비트 인코딩 구현 Part 2 (Implementation of bit encoding Part 2)



반응형
LIST

비트 인코딩 구현 Part 1 (Implementation of bit encoding)



반응형
LIST

전체 비트개수 기록 (Record total number of bits)



반응형
LIST

비트 인코딩 이론 (Bit encoding theory)



반응형
LIST

허프만 트리 복구 (Rebuilding Huffman tree)



반응형
LIST

파일로부터 허프만코드 복구 (Extracting Huffman codes from file)



반응형
LIST

디코딩 시작 (Begin the decoding of Huffman encoded file)



반응형
LIST

 허프만 트리 저장하기 (Recording Huffman tree)



반응형
LIST

인코딩 파일 이름 만들기 (Generating file name for Huffman encoding) 



반응형
LIST

허프만 코드테이블 만들기


(Making Huffman code table)



반응형
LIST

인코딩 파일 포맷 2



반응형
LIST

인코딩 파일 포맷 1



반응형
LIST

인코딩 파일 이론 



반응형
LIST

시그널



시스템프로그래밍_9차시.pdf


반응형
LIST

Huffman code 생성 구현



반응형
LIST

Huffman code 생성 이론



반응형
LIST

Huffman tree 구현



반응형
LIST

+ Recent posts