컬러이미지는 웹서버를 거쳐야 화면에 출력될수 있다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
//////////////
// 전역 변수부
//////////////
let inCanvas, inCtx, inPaper; // 입력 영상 관련
let outCanvas, outCtx, outPaper; // 출력 영상 관련
let inImage, inH, inW; // 2차원배열, 높이, 폭
let outImage, outH, outW; // 2차원배열, 높이, 폭
let inFile;
//////////////
// 공통 함수부 : Open(), Display().....
//////////////
function init() {
inCanvas = document.getElementById("inCanvas"); // 도화지
inCtx = inCanvas.getContext("2d"); // 물감, 붓이 들은 통
inCtx.beginPath();
inCtx.fillStyle="white"
inCtx.rect(30,30,490,490);
inCtx.fill();
inCtx.font="20px Gothic"
inCtx.fillStyle="black"
inCtx.fillText("inImage 사진",215,275);
outCanvas = document.getElementById("outCanvas"); // 도화지
outCtx = outCanvas.getContext("2d"); // 물감, 붓이 들은 통
outCtx.beginPath();
outCtx.fillStyle="white"
outCtx.rect(30,30,490,490);
outCtx.fill();
outCtx.font="20px Gothic"
outCtx.fillStyle="black"
outCtx.fillText("outImage 사진",215,275);
}
function openImage() {
//inFile = document.getElementById("inFile").files[0]; // 선택한 RAW 파일(LENNA512.RAW)
var fileNum=document.getElementById('fileNum').value;//"55","5"
if(parseInt(fileNum)<10)
fileNum="0"+fileNum;//"05"
else
fileNum=fileNum;
var inFname="Nature99(Small)/picture"+fileNum+".jpg";//Nature99(Small)/picture05.jpg
//그림 파일 --> 이미지 객체
var imageObject = new Image();//빈이미지객체생성
imageObject.src=inFname;//파일이 이미지 객체에 쏙 들어감.
imageObject.onload=function() {
//중요! 입력영상 크기 알아내기
inH = imageObject.height;
inW = imageObject.width;
// 도화기 크기를 이미지 크기로 조절
inCanvas.height = inH;
inCanvas.width = inW;
//이미지 객체-->캔버스(화면)
inCtx.drawImage(imageObject,0,0,inW,inH);
//Image Object에서 화면에 출력 했고 이제 RAM으로 이동해야함
//메모리 할당(3차원 배열)
inImage = new Array(3);//3면 4차원 배열로 하면 투명도 까지 해볼수 있다.
for(var m=0;m<3;m++){
inImage[m] = new Array(inH);
for(let n=0; n<inH; n++)
inImage[m][n] = new Array(inW);
}
//--중요!--캔버스의 이미지(화면) --> 배열의 칼라로 추출
var colorBlob = inCtx.getImageData(0,0,inW,inH);//원하는 부분 만큼만 뽑아올수 있다.
var R,G,B,Alpha;//Alpha는 투명도 값
//이미지를 뽑아옴 2차원배열로 가자!!
for(var i=0;i<inH;i++){
for(var k=0;k<inW;k++){
var pos = (i*inW + k)*4;//1픽셀 == 4byte
R = colorBlob.data[pos+0];
G = colorBlob.data[pos+1];
B = colorBlob.data[pos+2];
Alpha = colorBlob.data[pos+3];
inImage[0][i][k]=R;
inImage[1][i][k]=G;
inImage[2][i][k]=B;
//inImage[3][i][k]=Alpha;//alpha는 안 쓰니까 생략
}
}
}
}
function displayImage() {
// 도화기 크기를 이미지 크기로 조절
outCanvas.height = outH;
outCanvas.width = outW;
outPaper= outCtx.createImageData(outW, outH); // 이미지 크기의 빈 종이를 준비
//W와 H를 잘구별해줘야하는데 테스트하고 바꾸는게 나음 굳이 기억ㄴㄴ
for (let i=0; i<outH; i++) {
for (let k=0; k<outW; k++) {
let R = outImage[0][i][k];
let G = outImage[1][i][k];
let B = outImage[2][i][k];
outPaper.data[(i*outW + k)*4 + 0] = R; // Red
outPaper.data[(i*outW + k)*4 + 1] = G; // Green
outPaper.data[(i*outW + k)*4 + 2] = B; // Blue
outPaper.data[(i*outW + k)*4 + 3] = 255; // Alpha (투명도)
}
}
outCtx.putImageData(outPaper,0,0);
}
let algoNum;
function selectAlgorithm(selNum) {
algoNum = parseInt(selNum.value);
switch (algoNum) {
case 101://동일영상
equalImage();break;
case 102://반전영상
reverseImage_mouse();break;
case 103://영상더하기
lightImage_mouse();break;
case 104://영상빼기
darkImage_mouse();break;
case 105://영상곱하기
gopImage_mouse();break;
case 106://영상나누기
divImage_mouse();break;
case 107://흑백127기준
bwImage_mouse();break;
case 108://흑백평균기준
avgImage_mouse();break;
case 109://흑백중앙값기준
bwMiddleImage();break;
case 110://파라볼라 캡
paraCapImage_mouse();break;
case 111://파라볼라 컵
paraCupImage_mouse();break;
case 112://감마
gammaImage_mouse();break;
case 113://그레이스케일
grayImage_mouse();break;
case 114://채도 변환
saturImage_mouse();break;
case 115://명도 변환
intensityImage_mouse();break;
case 116://오렌지추출(컴퓨터비전)
orangeImage_mouse();break;
case 201:// 상하미러링
udImage_mouse();break;
case 202:// 좌우미러링
lrImage_mouse();break;
case 203:// 영상이동
swapImage_mouse();break;
case 204:// 영상회전
rotateImage_mouse();break;
case 205:// 영상회전 90도
image90_mouse();break;
case 206:// 영상축소
zoomOutImage_mouse();break;
case 207:// 영상확대
zoomInImage_mouse();break;
case 208:// 영상확대(백워딩)
zoomInImage2();break;
case 209:// 반시계회전
spinImage_mouse();break;
case 301:// 엠보싱
embossImage_mouse();break;
case 302:// 블러링
blurrImage_mouse();break;
case 303:// 샤프닝
sharpenImage_mouse();break;
case 304:// 가우시안
gaussianImage_mouse();break;
case 305:// 고주파 샤프닝
hpfSharpImage_mouse();break;
case 306:// 저주파 통과 샤프닝
OnLpfImage_mouse();break;
case 307:// 에지 검출 이동과 차분
sadImage_mouse();break;
case 308:// 유사연산자
opImage_mouse();break;
case 309: //로버츠 알고리즘
robertsImage_mouse();break;
case 310: //소벨 알고리즘
sobelImage_mouse();break;
case 311: //프리윗 알고리즘
prewittImage_mouse();break;
case 312: //라플라시안 알고리즘
laplacianImage_mouse();break;
case 313: //로그 알고리즘
logImage_mouse();break;
case 314: //dog 알고리즘
dogImage_mouse();break;
case 315: //모자이크
mosaic_mouse();break;
case 401:// 스트레칭
stretchImage_mouse();break;
case 402:// 엔드-인
endInImage_mouse();break;
case 403:// 평활화
equalizeImage_mouse();break;
}
}
////////////////////////////////////////////////
//이벤트리스너
///////////////////////////////////////////////
let startX, startY, endX, endY;
let pressYN = false;
let imageData;//마우스 클릭 시점의 화면
///////마우스 처리 공통함수 --> //////////////
function __downMouse(event){
startX = event.offsetX;
startY = event.offsetY;
pressYN=true;
//현재 상태를 보관하기
imageData = inCtx.getImageData(0,0,inCanvas.width, inCanvas.height);
//alert(startX+","+startY);
}
function __upMouse(event){
inCtx.putImageData(imageData,0,0);
endX = event.offsetX;
endY = event.offsetY;
//선택한 네모박스 안쪽만 영상처리 되기
//시작과 끝을 재배치
if(startX > endX){
let tmp = startX;
startX = endX;
endX = tmp;
}
if(startY > endY){
let tmp = startY;
startY = endY;
endY = tmp;
}
//마우스 이벤트 리스너 끄기
inCanvas.removeEventListener("mousedown",__downMouse,false);
inCanvas.removeEventListener("mouseup",__upMouse,false);
inCanvas.removeEventListener("mousemove",__moveMouse,false);
pressYN= false;
switch (algoNum) {
case 101://동일영상
equalImage();break;
case 102://반전영상
reverseImage();break;
case 103://영상더하기
lightImage();break;
case 104://영상빼기
darkImage();break;
case 105://영상곱하기
gopImage();break;
case 106://영상나누기
divImage();break;
case 107://흑백127기준
bwImage();break;
case 108://흑백평균기준
avgImage();break;
case 110://파라볼라 캡
paraCapImage();break;
case 111://파라볼라 컵
paraCupImage();break;
case 112://감마
gammaImage();break;
case 113://그레이스케일
grayImage();break;
case 114://채도 변환
saturImage();break;
case 115://명도 변환
intensityImage();break;
case 116://오렌지추출(컴퓨터비전)
orangeImage();break;
case 201:// 상하미러링
udImage();break;
case 202:// 좌우미러링
lrImage();break;
case 203:// 영상이동
swapImage();break;
case 204:// 영상회전
rotateImage();break;
case 205:// 영상회전 90도
image90();break;
case 206:// 영상축소
zoomOutImage();break;
case 207:// 영상확대
zoomInImage();break;
case 208:// 영상확대(백워딩)
zoomInImage2();break;
case 209:// 반시계회전
spinImage();break;
case 301:// 엠보싱
embossImage();break;
case 302:// 블러링
blurrImage();break;
case 303:// 샤프닝
sharpenImage();break;
case 304:// 가우시안
gaussianImage();break;
case 305:// 고주파 샤프닝
hpfSharpImage();break;
case 306:// 저주파 통과 샤프닝
OnLpfImage();break;
case 307:// 에지 검출 이동과 차분
sadImage();break;
case 308:// 유사연산자
opImage();break;
case 309: //로버츠 알고리즘
robertsImage();break;
case 310: //소벨 알고리즘
sobelImage();break;
case 311: //프리윗 알고리즘
prewittImage();break;
case 312: //라플라시안 알고리즘
laplacianImage();break;
case 313: //로그 알고리즘
logImage();break;
case 314: //dog 알고리즘
dogImage();break;
case 315: //모자이크
mosaic();break;
case 401:// 스트레칭
stretchImage();break;
case 402:// 엔드-인
endInImage();break;
case 403:// 평활화
equalizeImage();break;
}
//alert(startX+","+startY);
pressYN=false;
}
function __moveMouse(event){
if(!pressYN)
return;
inCtx.putImageData(imageData,0,0);
endX = event.offsetX;
endY = event.offsetY;
inCtx.beginPath();//선그리기 시작
inCtx.strokeStyle = 'blue';
inCtx.lineWidth =1;
inCtx.rect(startX, startY, (endX-startX),(endY-startY));
inCtx.stroke();
inCtx.closePath();
}
////////<--마우스 처리 공통함수 //////////////////
function onEventListener(){
inCanvas.addEventListener("mousedown",__downMouse,false);
inCanvas.addEventListener("mouseup",__upMouse,false);
inCanvas.addEventListener("mousemove",__moveMouse,false);
}
//////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////
////////////////////////
/////RGB --> HSV변환함수
////////////////////////
function rgb2hsv(r, g, b) {//RGB --> HSV변환함수
var max = Math.max(r, g, b), min = Math.min(r, g, b),
d = max - min,
h,
s = (max === 0 ? 0 : d / max),
v = max / 255;
switch (max) {
case min: h = 0; break;
case r: h = (g - b) + d * (g < b ? 6: 0); h /= 6 * d; break;
case g: h = (b - r) + d * 2; h /= 6 * d; break;
case b: h = (r - g) + d * 4; h /= 6 * d; break;
}
return {
h: h, s: s, v: v
};
}
function hsv2rgb(h, s, v) {//HSV-->RGB 변환함수
var r, g, b, i, f, p, q, t;
h = h*360; s = s*100; v = v*100;
h = Math.max(0, Math.min(360, h));
s = Math.max(0, Math.min(100, s));
v = Math.max(0, Math.min(100, v));
h /= 360; s /= 100; v /= 100;
i = Math.floor(h * 6);
f = h * 6 - i;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
switch (i % 6) {
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
return {
r: Math.round(r * 255),
g: Math.round(g * 255),
b: Math.round(b * 255)
};
}
</script>
<style>
.abc{
padding: 50px;
}
</style>
</head>
<body onload="init()" class = "abc">
<center>
<h1>칼라 영상 처리 (Beta 7)</h1>
<table>
<form>
<tr>
<td> <input type="checkbox" id="mouseEnable">사각형 선택<input type="number" id="fileNum">
<input type="button" id="inFile" value="이미지 열기" onclick="openImage()"><br></td>
<td><select name="pixel" onchange="selectAlgorithm(this.form.pixel)">
<ul>
<li><option value="0">*화소점 처리*</option>
<li><option value="101">동일 영상</option>
<li><option value="102">영상 반전</option>
<li><option value="103">영상 더하기</option>
<li><option value="104">영상 빼기</option>
<li><option value="105">영상 곱하기</option>
<li><option value="106">영상 나누기</option>
<li><option value="107">흑백127기준</option>
<li><option value="108">흑백평균기준</option>
<li><option value="109">흑백중앙값기준</option>
<li><option value="110">파라볼라 캡</option>
<li><option value="111">파라볼라 컵</option>
<li><option value="112">감마</option>
<li><option value="113">그레이스케일</option>
<li><option value="114">채도 변환</option>
<li><option value="115">명도 변환</option>
<li><option value="116">오렌지 추출(컴퓨터 비전)</option>
</ul>
</select>
<select name="geometry" onchange="selectAlgorithm(this.form.geometry)">
<ul>
<li><option value="0">*기하학 처리*</option>
<li><option value="201">상하 미러링</option>
<li><option value="202">좌우 미러링</option>
<li><option value="203">영상 이동</option>
<li><option value="204">영상 회전</option>
<li><option value="205">영상 회전 90도</option>
<li><option value="206">영상 축소</option>
<li><option value="207">영상 확대</option>
<li><option value="208">영상 확대(백워딩)</option>
<li><option value="209">반시계 회전</option>
</ul>
</select>
<select name="area" onchange="selectAlgorithm(this.form.area)">
<ul>
<li><option value="0">*화소영역 처리*</option>
<li><option value="301">엠보싱</option>
<li><option value="302">블러링</option>
<li><option value="303">샤프닝</option>
<li><option value="304">가우시안</option>
<li><option value="305">고주파 샤프닝</option>
<li><option value="306">저주파통과 고주파</option>
<li><option value="307">이동과 차분</option>
<li><option value="308">유사연산자</option>
<li><option value="309">로버츠마스크 수평/수직</option>
<li><option value="310">소벨마스크 수평/수직</option>
<li><option value="311">프리윗마스크 수평/수직</option>
<li><option value="312">라플라시안</option>
<li><option value="313">로그</option>
<li><option value="314">도그</option>
<li><option value="315">모자이크</option>
</ul>
</select>
<select name="histo" onchange="selectAlgorithm(this.form.histo)">
<ul>
<li><option value="0">*히스토그램 처리*</option>
<li><option value="401">스트레칭</option>
<li><option value="402">엔드-인</option>
<li><option value="403">평활화</option>
</ul>
</select></td>
</form></tr>
<tr><br></tr>
<tr><br></tr><tr><br></tr><tr><br></tr>
<tr>
<td><canvas id="inCanvas" style="background-color:rgb(253, 206, 119)"
width="550" height="550"></canvas></td>
<td><canvas id="outCanvas" style="background-color:rgb(179, 160, 223)"
width="550" height="550"></canvas></td></tr>
</table>
</center>
</body>
</html>
'OpenCV없는 컬러영상처리 및 마우스 이벤트' 카테고리의 다른 글
마우스 이벤트를 통한 칼라영상처리 (0) | 2022.09.25 |
---|---|
히스토그램 처리하기 (0) | 2022.09.23 |
화소 영역 처리 (0) | 2022.09.23 |
기하학처리 (0) | 2022.09.23 |
화소점처리 (0) | 2022.09.23 |