2021/04/01(목)
히스토그램 스트레칭/히스토그램 엔드인/히스토그램 평활화 알고리즘 참고
https://cordingdoah.tistory.com/94
이번 게시물에서는 컬러사진 영상처리를 해보겠다
컬러 영상처리 알고리즘 : 흑백처리, 부분흑백처리, 부분 색반전 구현하겠다
컬러영상처리 원리
- 기존에 흑백 사진 원리와 마찬가지로 디스크에 있는 이미지를 불러와 배열에 저장하고 영상처리를 하여 화면에 내보내는데 차이점은 컴퓨터에서 보여지는 Red, Green, Blue로 이루어진 3차원 배열이 필요하다
컬러사진 화면에 띄우기
function openImage() {
init();
inFile = document.getElementById('selectFile').files[0];
// 그림파일 --> 이미지 객체
var inImage = new Image(); // 빈 이미지 객체 생성
inImage.src = inFile.name;
inImage.onload = function () {
// 입력 파일의 크기를 알아냄 (중요!)
inWidth = inImage.width;
inHeight = inImage.height;
// 캔버스 크기를 결정
inCanvas.width = inWidth;
inCanvas.height = inHeight;
inCtx.drawImage(inImage, 0, 0, inWidth, inHeight);
// 입력 3차원 배열을 준비
inImageArray = new Array(3); // 3장짜리 배열 (R, G, B)
for (var i = 0; i < 3; i++) {
inImageArray[i] = new Array(inHeight);
for (var k = 0; k < inHeight; k++)
inImageArray[i][k] = new Array(inWidth);
}
// 출력된 캔버스에서 픽셀값 뽑기
var imageData = inCtx.getImageData(0, 0, inWidth, inHeight);
var R, G, B, Alpha;
for (var i = 0; i < inHeight; i++) {
for (var k = 0; k < inWidth; k++) {
px = (i * inWidth + k) * 4; // 1픽셀 = 4byte
R = imageData.data[px + 0];
G = imageData.data[px + 1];
B = imageData.data[px + 2];
// Alpha = imageData.data[px + 3];
inImageArray[0][i][k] = String.fromCharCode(R);
inImageArray[1][i][k] = String.fromCharCode(G);
inImageArray[2][i][k] = String.fromCharCode(B);
}
}
equalImage();
}
}
기존의 raw파일을 띄웠던 것과 비슷하지만 차이점은 R,G,B 변수를 따로 설정하여 3차원 배열에 저장하여 출력
<원본이미지 출력배열에 저장 메소드>
function equalImage() {
// (중요!) 출력 영상의 크기를 결정... 알고리즘에 따름.
outHeight = inHeight;
outWidth = inWidth;
// 출력 3차원 배열을 준비
outImageArray = new Array(3); // 512짜리 1차원 배열
for (var i = 0; i < 3; i++) {
outImageArray[i] = new Array(outHeight); // 512짜리 1차원 배열
for (var k = 0; k < outHeight; k++)
outImageArray[i][k] = new Array(outWidth);
}
// ***** 진짜 영상처리 알고리즘 *****
for (var rgb = 0; rgb < 3; rgb++) {
for (var i = 0; i < inHeight; i++) {
for (var k = 0; k < inWidth; k++) {
outImageArray[rgb][i][k] = inImageArray[rgb][i][k];
}
}
}
displayImage();
}
<컬러이미지 화면에 출력 메소드>
function displayImage() {
// 캔버스 크기를 결정
inCanvas.height = outHeight;
inCanvas.width = outWidth;
var R, G, B;
inPaper = inCtx.createImageData(outWidth, outHeight);
for (var i = 0; i < outHeight; i++) {
for (var k = 0; k < outWidth; k++) {
R = outImageArray[0][i][k].charCodeAt(0); // Byte 문자를 숫자로.
G = outImageArray[1][i][k].charCodeAt(0); // Byte 문자를 숫자로.
B = outImageArray[2][i][k].charCodeAt(0); // Byte 문자를 숫자로.
inPaper.data[(i * outWidth + k) * 4 + 0] = R;
inPaper.data[(i * outWidth + k) * 4 + 1] = G;
inPaper.data[(i * outWidth + k) * 4 + 2] = B;
inPaper.data[(i * outWidth + k) * 4 + 3] = 255;
}
}
inCtx.putImageData(inPaper, 0, 0);
}
--> 컬러영상 결과화면
<흑백처리>
//그레이 스케일
function grayScale() {
// ***** 진짜 영상처리 알고리즘 *****
var R, G, B;
for (var i = 0; i < outHeight; i++) {
for (var k = 0; k < outWidth; k++) {
R = outImageArray[0][i][k].charCodeAt(0);
G = outImageArray[1][i][k].charCodeAt(0);
B = outImageArray[2][i][k].charCodeAt(0);
var RGB = parseInt((R + G + B) / 3);
outImageArray[0][i][k] = String.fromCharCode(RGB);
outImageArray[1][i][k] = String.fromCharCode(RGB);
outImageArray[2][i][k] = String.fromCharCode(RGB);
}
}
displayImage();
clickEvent();
}
각각의 RGB 값을 더해 평균값을 구해서 모두 같은 값으로 넣어주면 된다
--> 흑백처리 결과화면
<부분 흑백처리>
부분 흑백처리는 마우스로 클릭하고 드래그하고 떼면 그 부분만 흑백처리 해주는 처리를 구현했는데
마우스 이벤트가 필요하다
//부분 흑백
var xx, xy, ex, ey;
function bwImage_Mouse() {
clickEventDown();
inCanvas.addEventListener("mousedown", downMouse, false);
inCanvas.addEventListener("mouseup", upMouse, false);
function downMouse(e) {
xx = e.offsetX;
xy = e.offsetY;
}
function upMouse(e) {
ex = e.offsetX;
ey = e.offsetY;
if (xx > ex) {
var tmp = xx;
xx = ex;
ex = tmp;
}
if (xy > ey) {
var tmp = xy;
xy = ey;
ey = tmp;
}
//네모칸 그리기
inCtx.beginPath();
inCtx.strokeStyle = 'Green'; //붓색깔
inCtx.rect(xx, xy, (ex - xx), (ey - xy));
inCtx.stroke();
inCtx.closePath();
inCanvas.removeEventListener("mousedown", downMouse, false);
inCanvas.removeEventListener("mouseup", upMouse, false);
__bwImage_Mouse();
clickEvent();
}
}
1. 클릭하면 mouseDown함수를 수행 ( 현재 좌표 xx,xy 변수에 저장) 하고
2. 드래그 후 마우스를떼면 mouseUp함수를 수행 ( 현재 좌표 ex,ey 변수에 저장)
3. 만약 마우스를 뗐을 때 좌표가 처음 시작 좌표보다 작으면 두 값을 서로 바꿔주기
4. 네모칸을 그리고 이벤트를 없애 준 후 __bwImage_Mouse()함 수 호출
//부분적 흑백처리
function __bwImage_Mouse() {
// ***** 진짜 영상처리 알고리즘 *****
var R, G, B;
for (var i = 0; i < outHeight; i++) {
for (var k = 0; k < outWidth; k++) {
if ((xx <= k && ex >= k) && (xy <= i && ey >= i)) {
R = outImageArray[0][i][k].charCodeAt(0);
G = outImageArray[1][i][k].charCodeAt(0);
B = outImageArray[2][i][k].charCodeAt(0);
var RGB = parseInt((R + G + B) / 3);
if (RGB > 127)
RGB = 255;
else
RGB = 0;
outImageArray[0][i][k] = String.fromCharCode(RGB);
outImageArray[1][i][k] = String.fromCharCode(RGB);
outImageArray[2][i][k] = String.fromCharCode(RGB);
}
else {
outImageArray[0][i][k] = outImageArray[0][i][k];
outImageArray[1][i][k] = outImageArray[1][i][k];
outImageArray[2][i][k] = outImageArray[2][i][k];
}
}
}
displayImage();
}
좌표의 범위에 해당하는 배열들만 흑백처리를 하고 아니라면 그냥 출력
** 부분 흑백 처리 같은 경우 0과 255로만 표현해서 완전한 흑백처리로 구현했다
그렇기 때문에 일반적인 흑백 처리와 다르게 if문을 이용해서 127보다 크면 255로 127보다 작으면 0으로 치환했다
--> 부분 흑백처리 결과화면
<부분 색반전>
//색반전
function reversal() {
clickEventDown();
inCanvas.addEventListener("mousedown", downMouse, false);
inCanvas.addEventListener("mouseup", upMouse, false);
function downMouse(e) {
xx = e.offsetX;
xy = e.offsetY;
}
function upMouse(e) {
ex = e.offsetX;
ey = e.offsetY;
if (xx > ex) {
var tmp = xx;
xx = ex;
ex = tmp;
}
if (xy > ey) {
var tmp = xy;
xy = ey;
ey = tmp;
}
//네모칸 그리기
inCtx.beginPath();
inCtx.strokeStyle = 'Green'; //붓색깔
inCtx.rect(xx, xy, (ex - xx), (ey - xy));
inCtx.stroke();
inCtx.closePath();
inCanvas.removeEventListener("mousedown", downMouse, false);
inCanvas.removeEventListener("mouseup", upMouse, false);
__reversal_Mouse();
clickEvent();
}
}
색반전도 부분 흑백처리와 마찬가지로 처리
//색반전
function __reversal_Mouse() {
// ***** 진짜 영상처리 알고리즘 *****
var R, G, B;
for (var i = 0; i < outHeight; i++) {
for (var k = 0; k < outWidth; k++) {
if ((xx <= k && ex >= k) && (xy <= i && ey >= i)) {
R = 255 - outImageArray[0][i][k].charCodeAt(0);
G = 255 - outImageArray[1][i][k].charCodeAt(0);
B = 255 - outImageArray[2][i][k].charCodeAt(0);
var RGB = parseInt((R + G + B) / 3);
outImageArray[0][i][k] = String.fromCharCode(RGB);
outImageArray[1][i][k] = String.fromCharCode(RGB);
outImageArray[2][i][k] = String.fromCharCode(RGB);
}
else {
outImageArray[0][i][k] = outImageArray[0][i][k];
outImageArray[1][i][k] = outImageArray[1][i][k];
outImageArray[2][i][k] = outImageArray[2][i][k];
}
}
}
displayImage();
}
흑백처리와 동일하게 좌표 사이에 있는 값만 색반전 처리, 범위에 있는 값이 아니라면 그냥 출력
--> 색반전 결과화면
'코딩 연습장 > Javascript' 카테고리의 다른 글
Python / JavaScript 이용한 지역별 전기차 충전소 지도 출력 프로젝트 - 2 (html 웹페이지 만들기) (0) | 2021.07.02 |
---|---|
자바스크립트를 이용한 개인 프로젝트 - 13(마우스 클릭 이벤트) (0) | 2021.06.16 |
자바스크립트를 이용한 개인 프로젝트 - 11(영상 처리 알고리즘) (0) | 2021.06.16 |
자바스크립트를 이용한 개인 프로젝트 - 10(영상 처리 알고리즘) (0) | 2021.06.15 |
자바스크립트를 이용한 개인 프로젝트 - 9(영상 처리 알고리즘) (0) | 2021.06.15 |