코딩 연습장/Javascript

자바스크립트를 이용한 개인 프로젝트 - 5(영상 처리 알고리즘)

Do아 2021. 6. 14. 15:13
728x90

2021/04/01(목)

 

 

 

 

슬라이드 화면구현과 각각의 메인화면의 뒷배경은 아래 글을 보고 참고

https://cordingdoah.tistory.com/81

 

자바스크립트 이용한 개인 프로젝트 - 1(첫 화면, 슬라이드 화면)

2021/04/01(목) 자바스크립트를 이용하여 영상처리 할 수 있는 프로젝트 설명 전체적인 프로젝트 컨셉 : 다양한 영상처리의 컨셉을 보여주기 위해 디즈니 영화를 주제로 잡아 구성을 했습니다. - 인

cordingdoah.tistory.com

https://cordingdoah.tistory.com/85

 

자바스크립트를 이용한 개인 프로젝트 - 2(인어 공주 화면)

2021/04/01(목) 자바스크립트를 활용하여 영상처리 프로젝트 : 첫 메인 화면 구현(첫 슬라이드) <메인화면의 구성> index.html이라는 메인html 위에 물결이 치는 모습을 구현한 module을 크기에 맞게 띄우

cordingdoah.tistory.com

 

 

 

 

<영상처리 알고리즘>

- 이번에는 각각 메인화면에서 사진을 가져와서 캔버스에 영상처리를 적용하는 알고리즘을 구현하는 것을 리뷰해보겠다

 

알고리즘 구현에 앞서 영상처리를 어떤 과정을 통해 웹에 구현이 되는지 구성도를 보자!

1. 디스크의 있는 raw(흑백파일)을 가져온다

2. 사진의 크기에 맞게 inImageArray 생성 후

3. 사진의 픽셀이 inImageArray 배열형태로 들어오게 된다 

4. 영상처리 알고리즘을 통해 각 픽셀이 처리 

5. outImageArray 배열에 저장되고 saveImage()함수를 통해 디스크에 저장

6. displayImage() 함수를 통해 화면에 출력

--> 이러한 과정을 가지고 처리된 영상이 화면에 출력되는 것을 알 수 있음

 

 

 

 

자! 이제 영상처리를 구현하는 알고리즘을 코딩해보자

 

먼저 화면에 출력해줄 캔버스를 만들어 주자 outCanvas에 영상처리된 사진을 출력하겠다

<!DOCTYPE html>
<html>

<head>

    <link rel="stylesheet" type="text/css" href="style.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@700&display=swap" rel="stylesheet">
    <script type="module" src="./app.js" defer>
    </script>

    <script>
        var inFile;
        var inImageArray, inWidth, inHeight;
        var outCanvas, outCtx, outImageArray;
        var outWidth, outHeight, outPaper;

        //초기화 : 캔버스 생성
        function init() {
            outCanvas = document.getElementById('outCanvas');
            outCtx = outCanvas.getContext('2d');
        }
	</script>
</head>
<body>
<div class="canvasEdge">
        <div class="KHC">
            <canvas id="outCanvas" width="100" height="100" style="background: rgba(0, 0, 0, 0);"></canvas>
        </div>
    </div>
 </body>
 </html>

 

 

 

 

 

이제부터 진짜! 알고리즘 

 

<파일 선택>

-파일을 선택하면 배열에 저장하고 출력하는 메소드

//파일 선택 메소드
        function selectRawFile() {

            init();

            inFile = document.getElementById('selectFile').files[0];
            // 중요! 코드 (영상의 크기를 파악)
            inWidth = inHeight = Math.sqrt(inFile.size);
            // 입력 2차원 배열을 준비
            inImageArray = new Array(inHeight); // 1차원 배열
            for (var i = 0; i < inHeight; i++)	// 2차원 배열
                inImageArray[i] = new Array(inWidth);

            // RAW 파일  --> 2차원 배열
            var reader = new FileReader();
            reader.readAsBinaryString(inFile);
            reader.onload = function () {
                var bin = reader.result; // 파일을 덩어리(bin)로 읽었음
                // 덩어리(bin)에서 한점한점씩 뽑아서, 배열에 넣기
                for (var i = 0; i < inHeight; i++) {
                    for (var k = 0; k < inWidth; k++) {
                        var sPixel = (i * inHeight + k);
                        var ePixel = (i * inHeight + k) + 1;
                        inImageArray[i][k] = bin.slice(sPixel, ePixel); // 1개픽셀-->배열
                    }
                }
                equalImage();
            }
        }

사진 파일을 inImageArray(원본)에 넣어놓고 영상처리를 할 수 있도록 구현하기 위해

 

 

 

 

<원본이미지>

- inImageArray에 저장된 사진 파일의 원본을  outImageArray에 그대로 넣어줌

 //원본 출력
        function equalImage() {  //동일 영상 알고리즘

            outHeight = inHeight;
            outWidth = inWidth;
            // 출력 2차원 배열을 준비
            outImageArray = new Array(outHeight); // 256짜리 1차원 배열
            for (var i = 0; i < outHeight; i++)
                outImageArray[i] = new Array(outWidth);

            // ***** 진짜 영상처리 알고리즘 *****
            for (var i = 0; i < inHeight; i++) {
                for (var k = 0; k < inWidth; k++) {
                    outImageArray[i][k] = inImageArray[i][k];
                }
            }
            displayImage();
        }

 

 

 

 

 

<화면 출력>

- 저장된 outImageArray 배열을 캔버스에 출력해주는 메소드

 //캔버스에 이미지 출력
        function displayImage() {
            // 캔버스 크기를 결정
            outCanvas.width = outWidth;
            outCanvas.height = outHeight;
            outPaper = outCtx.createImageData(outHeight, outWidth); //종이 붙였음.
            for (var i = 0; i < outHeight; i++) {
                for (var k = 0; k < outWidth; k++) {
                    var charValue = outImageArray[i][k].charCodeAt(0); // 깨진문자를 숫자로.
                    outPaper.data[(i * outWidth + k) * 4 + 0] = charValue; // R
                    outPaper.data[(i * outWidth + k) * 4 + 1] = charValue; // G
                    outPaper.data[(i * outWidth + k) * 4 + 2] = charValue; // B
                    outPaper.data[(i * outWidth + k) * 4 + 3] = 255; // Alpha
                }
            }
            outCtx.putImageData(outPaper, 0, 0);
        }

 

 

 

 

위까지 구현한 결과

파일을 가져오면 캔버스 화면에 배열의 형태로 띄울수 있다

 

 

 

 

 

raw파일 색표현(참고)

<밝게하기>

//밝게하기
        function brighteImage() {

            clickEventDown();

            // ***** 진짜 영상처리 알고리즘 *****

            var value = parseInt(prompt("밝게할 값", "0"));
            for (var i = 0; i < outHeight; i++) {
                for (var k = 0; k < outWidth; k++) {
                    // 문자 --> 숫자
                    pixel = outImageArray[i][k].charCodeAt(0);
                    // **** 요기가 핵심 알고리즘. (밝게하기)
                    if (pixel + value > 255)
                        pixel = 255;
                    else
                        pixel += value;
                    // 숫자 --> 문자
                    outImageArray[i][k] = String.fromCharCode(pixel);
                }
            }

            displayImage();
            clickEvent();
        }

1. prompt로 얼마나 밝게할 것인지 받아오기 초기값은 0 

2. 2차원 사진 배열의 크기만큼 이중 반복문 

3. 각각의 배열의 요소를 숫자로 바꿔서 pixel변수에 저장

4. pixel과 밝게하고 싶은 값을 더해서 최대 밝은 값인 255보다 크면 255로 지정

5. 255보다 작으면 pixel과 밝게하고 싶은 값을 더함

6. 결과값을 다시 문자로 바꿔서 배열에 저장

7. displayImage() 함수를 통해 배열을 출력

** clickEventDown, clickEvent는 캔버스를 클릭했을 때 영상이 적용된 것과 원본 화면과 비교할 수 있도록 만든 이벤트인데 다른 게시물에서 다루도록 하겠다

 

 

 

--> 100를 밝게한 결과 화면

 

 

 

 

 

<흑백처리>

        //어둡게 하기
        function darkImage() {

            clickEventDown();
            // ***** 진짜 영상처리 알고리즘 *****
            //평균값을 도출
            var valueSum = 0;
            for (var i = 0; i < outHeight; i++) {
                for (var k = 0; k < outWidth; k++) {
                    // 문자 --> 숫자
                    pixel = outImageArray[i][k].charCodeAt(0);
                    valueSum += pixel;
                }
            }
            var value = valueSum / (outHeight * outWidth);

            //평균값만큼 흑백처리
            for (var i = 0; i < outHeight; i++) {
                for (var k = 0; k < outWidth; k++) {
                    // 문자 --> 숫자
                    pixel = outImageArray[i][k].charCodeAt(0);
                    // **** 요기가 핵심 알고리즘. 흑백처리
                    if (pixel > value)
                        pixel = 255;
                    else
                        pixel = 0;
                    // 숫자 --> 문자
                    outImageArray[i][k] = String.fromCharCode(pixel);
                }
            }
            displayImage();
            clickEvent()
        }

 

 

어둡게 처리하기 같은 경우는 밝게하기와 다르게 사진의 평균값을 도출해 평균값보다 값이 크면 흰색 어두우면 검은색으로 처리

1. 평균값을 구하기 위해 모든 배열의 값을 더하고 크기만큼 나눠서 평균값 구하기

2. 각 배열의 요소(pixel)값이 평균값보다 높으면(채도가 밝으면) 255(흰색)으로 처리

3. 각 배열의 요소(pixel)값이 평균값보다 낮으면(채도가 어두우면) 0(검은색)으로 처리

4. 배열에 저장

5. displayImage로 출력

 

 

 

-->흑백처리 결과

 

 

 

 

 

다음 게시물에서 영상처리 알고리즘 계속...☺

728x90