본문 바로가기

OpenCV없는 컬러영상처리 및 마우스 이벤트

기하학처리

시연 영상(유튜브): https://youtu.be/1Sxv_qu4CcU


<원본이미지 상하미러링>

전체이미지변경 알고리즘
이벤트처리를 위한 부분처리 알고리즘
결과화면

 

function udImage(){ // 상하 미러링 
        // (중요!) 출력 이미지의 크기가 결정 -> 알고리즘에 의존..
        outH = inH;
        outW = inW;

        // 출력 영상의 3차원 메모리 할당
        outImage = new Array(3); // 3면
        for(let m = 0 ; m < 3 ; m++){
            outImage[m] = new Array(outH);
            for(let n = 0 ; n < outH ; n++){
                outImage[m][n] = new Array(outW);
            }
        }

        // ** 진짜 영상처리 알고리즘 **
    
        let a = 0;

        for(let i = 0 ; i < inH ; i++){
            for(let k = 0 ; k < inW ; k++){
                if((startX <= k && k <= endX ) && (startY <= i && i <= endY)) {
                    if(startX == 0){
                        outImage[0][i][k] = inImage[0][inH-i-1][k];
                        outImage[1][i][k] = inImage[1][inH-i-1][k];
                        outImage[2][i][k] = inImage[2][inH-i-1][k];
                    }else {      
                        outImage[0][i][k] = inImage[0][endY-a-1][k];
                        outImage[1][i][k] = inImage[1][endY-a-1][k];
                        outImage[2][i][k] = inImage[2][endY-a-1][k];
                    }

                }else {
                    outImage[0][i][k] = inImage[0][i][k];
                    outImage[1][i][k] = inImage[1][i][k];
                    outImage[2][i][k] = inImage[2][i][k];

                }
            }
            if((startY <= i && i <= endY)){
                a++;
            }
        }
            

        displayImage();
    }
    function udImage_mouse(){
        var mouseCheck= document.getElementById("mouseEnable");
            //사각형 선택이 체크가 안되었을때!
            if(!mouseEnable.checked){
                startX = startY=0;
                endX = inW;
                endY= inH;
                udImage();
                return;
            }
            //사각형 체크됨.
            //마우스 이벤트 리스너 켜기
            onEventListener();
    }

 

 

 


<원본이미지 좌우미러링>

전체이미지변경 알고리즘
이벤트처리를 위한 부분처리 알고리즘
결과화면

 function lrImage() {
        outH = inH;
        outW = inW;
        // 출력 영상의 3차원 메모리 할당
        outImage = new Array(3); // 3면
        for (var m = 0; m < 3; m++) {
          outImage[m] = new Array(outH);
          for (let n = 0; n < outH; n++) outImage[m][n] = new Array(outW);
        }
        let a = 0;
        // **** 진짜 영상처리 알고리즘 *****
        
          for (let i = 0; i < inH; i++) { 
              a=0;
            for (let k = 0; k < inW; k++) {
              if ((startX <= k && k < endX) && (startY <= i && i < endY)){
                if(startX == 0){
                    outImage[0][i][k] = inImage[0][i][inW - k - 1];
                    outImage[1][i][k] = inImage[1][i][inW - k - 1];
                    outImage[2][i][k] = inImage[2][i][inW - k - 1];
                }else {
                    outImage[0][i][k] = inImage[0][i][endX-a-1];
                    outImage[1][i][k] = inImage[1][i][endX-a-1];
                    outImage[2][i][k] = inImage[2][i][endX-a-1];
                }
              }else {
                    outImage[0][i][k] = inImage[0][i][k];
                    outImage[1][i][k] = inImage[1][i][k];
                    outImage[2][i][k] = inImage[2][i][k];
              }
              if((startX <= k && k <= endX)){
                    a++
                }
          }  
       
        }
        displayImage();
      }
    function lrImage_mouse(){
        var mouseCheck= document.getElementById("mouseEnable");
            //사각형 선택이 체크가 안되었을때!
            if(!mouseEnable.checked){
                startX = startY=0;
                endX = inW;
                endY= inH;
                lrImage();
                return;
            }
            //사각형 체크됨.
            //마우스 이벤트 리스너 켜기
            onEventListener();
    }

 

 


시연영상(유튜브): https://youtu.be/-FhNYX6Pa1w


<원본이미지 축소하기>

알고리즘
결과화면

function zoomOutImage(){
        let scale = parseInt(prompt("축소 크기 : ","2"));
        if(startX==0){
        outH=parseInt(inH/scale);
        outW=parseInt(inW/scale);

        outImage = new Array(3);//3면 
        for(var m=0;m<3;m++){
            outImage[m] = new Array(outH);
            for(let n=0; n<outH; n++)
                outImage[m][n] = new Array(outW);
        }
        for(var rgb=0;rgb<3;rgb++){
            for (let i=0; i<inH; i++) {
                for (let k=0; k<inW; k++) {
                    outImage[rgb][parseInt(i/scale)][parseInt(k/scale)]=inImage[rgb][i][k];
                }
            }
        }
    }
    else{
        outH=inH;
        outW=inW;

        outImage = new Array(3);//3면 
        for(var m=0;m<3;m++){
            outImage[m] = new Array(outH);
            for(let n=0; n<outH; n++)
                outImage[m][n] = new Array(outW);
        }
        for(var rgb=0;rgb<3;rgb++){
            for (let i=0; i<inH; i++) {
                for (let k=0; k<inW; k++) {
                    if ((startX <= k && k <= endX) && (startY <= i && i <= endY)){
                        outImage[rgb][parseInt((i/scale)+((endY-startY)/2))][parseInt((k/scale)+((endX-startX)/2))]=inImage[rgb][i][k];
                    }
                    else
                        outImage[rgb][i][k] = inImage[rgb][i][k];

                }

                
            }
        }
    }
        displayImage();

}
    function zoomOutImage_mouse(){
        var mouseCheck= document.getElementById("mouseEnable");
            //사각형 선택이 체크가 안되었을때!
            if(!mouseEnable.checked){
                startX = startY=0;
                endX = inW;
                endY= inH;
                zoomOutImage();
                return;
            }
            //사각형 체크됨.
            //마우스 이벤트 리스너 켜기
            onEventListener();
    }

 

 


<원본이미지 확대하기>

-포워딩확대는 이벤트 처리를 못했다. 이미지의 부분을 확대하면 이미지바깥에 커진 이미지가 나온다.

-내 프로젝트에서는 확대기능은 전체 이미지 처리만 가능

알고리즘
결과화면

 function zoomInImage(){
        let scale= parseInt(prompt("확대 크기: ","2"));

        outH=inH*scale;
        outW=inW*scale;

        outImage = new Array(3);//3면 
        for(var m=0;m<3;m++){
            outImage[m] = new Array(outH);
            for(let n=0; n<outH; n++)
                outImage[m][n] = new Array(outW);
        }
        for(var rgb=0;rgb<3;rgb++){
            for (let i=0; i<inH; i++) {
                for (let k=0; k<inW; k++) {
                    outImage[rgb][i*scale][k*scale]=inImage[rgb][i][k];
                }
            }
        }
        displayImage();

    }

 

 

 


<원본이미지 확대하기 (백워딩)>

-백워딩은 확대를 하면 인덱스 접근 불가 범위까지 가버려서 출력이 안나오는 오류가 발생한다.

-이벤트처리는 못하고 원본이미지 확대만 가능하다.

알고리즘
결과화면

 function zoomInImage2(){
        let scale= parseInt(prompt("확대 크기: ","2"));

        outH=inH*scale;
        outW=inW*scale;

        outImage = new Array(3);//3면 
        for(var m=0;m<3;m++){
            outImage[m] = new Array(outH);
            for(let n=0; n<outH; n++)
                outImage[m][n] = new Array(outW);
        }
        for(var rgb=0;rgb<3;rgb++){
            for (let i=0; i<outH; i++) {
                for (let k=0; k<outW; k++) {
                    outImage[rgb][i][k]= inImage[rgb][parseInt(i/scale)][parseInt(k/scale)];
                }
            }
        }
        displayImage();
    }

 


시연 영상(유튜브): https://youtu.be/NO7NClFzLqY


 

<원본이미지 영상 이동하기>

알고리즘
결과화면

function swapImage(){
        let x=parseInt(prompt("x축으로 이동","30"));
        let y=parseInt(prompt("y축으로 이동","30"));

        outW=inW;
        outH=inH;

        outImage = new Array(3);//3면 
        for(var m=0;m<3;m++){
            outImage[m] = new Array(outH);
            for(let n=0; n<outH; n++)
                outImage[m][n] = new Array(outW);
        }

        for(var rgb=0;rgb<3;rgb++){
            for (let i=0; i<inH; i++) {
                for (let k=0; k<inW; k++) {
                    if((startX <= k && k< endX )&&(startY <=i && i<endY)){
                        if((i+y)<outH&&(k+x)<outW)
                                outImage[rgb][i+y][k+x]=inImage[rgb][i][k];
                        else break;
                    }
                    else
                        outImage[rgb][i][k] = inImage[rgb][i][k];
                }
            }
        }
        displayImage();
    }
    function swapImage_mouse(){
        var mouseCheck= document.getElementById("mouseEnable");
            //사각형 선택이 체크가 안되었을때!
            if(!mouseEnable.checked){
                startX = startY=0;
                endX = inW;
                endY= inH;
                swapImage();
                return;
            }
            //사각형 체크됨.
            //마우스 이벤트 리스너 켜기
            onEventListener();
    }

 


<원본이미지 회전하기>

알고리즘
결과화면

function rotateImage(){
        let degree = parseFloat(prompt("회전각도를 입력하시오","45"));
        let radian = degree*Math.PI/180.0;
        if(startX==0){
        outH=parseInt(Math.abs(Math.cos(radian)*inH) + Math.abs(Math.cos(Math.PI/2-radian)*inW));
        outW= parseInt(Math.abs(Math.cos(radian)*inW) + Math.abs(Math.cos(Math.PI/2-radian)*inH));

        outImage = new Array(3);//3면 
        for(var m=0;m<3;m++){
            outImage[m] = new Array(outH);
            for(let n=0; n<outH; n++)
                outImage[m][n] = new Array(outW);
        }

        let xd, yd;
        
        let cx=parseInt(outH/2);
        let cy=parseInt(outW/2);

        for(var rgb=0;rgb<3;rgb++){
            for (let i=0; i<outH; i++) {
                for (let k=0; k<outW; k++) {
                    xd=parseInt(Math.cos(radian)*(i-cx)-Math.sin(radian)*(k-cy)+cx/outH*inH);
                    yd=parseInt(Math.sin(radian)*(i-cx) + Math.cos(radian)*(k-cy)+cy/outW*inW);
                    if((0<=xd && xd <inH) && (0<=yd && yd <inW))
                        outImage[rgb][i][k]=inImage[rgb][xd][yd];
                    else
                        outImage[rgb][i][k]=255;
                }
            }
        }
    }
    else{
        outH=inH;
        outW=inW;

        outImage = new Array(3);//3면 
        for(var m=0;m<3;m++){
            outImage[m] = new Array(outH);
            for(let n=0; n<outH; n++)
                outImage[m][n] = new Array(outW);
        }

        let xd, yd;
        
        let cx=parseInt(outH/2);
        let cy=parseInt(outW/2);

        for(var rgb=0;rgb<3;rgb++){
            for (let i=0; i<outH; i++) {
                for (let k=0; k<outW; k++) {
                    xd=parseInt(Math.cos(radian)*(i-cx)-Math.sin(radian)*(k-cy)+cx);
                    yd=parseInt(Math.sin(radian)*(i-cx) + Math.cos(radian)*(k-cy)+cy);
                    if((startX <= k && k< endX )&&(startY <=i && i<endY)){
                        if((0<=xd && xd <inH) && (0<=yd && yd <inW))
                            outImage[rgb][i][k]=inImage[rgb][xd][yd];
                        else
                            outImage[rgb][i][k]=255;
                    }
                    else
                        outImage[rgb][i][k] = inImage[rgb][i][k];
                }
            }
        }
    }
        displayImage();
    }
    function rotateImage_mouse(){
        var mouseCheck= document.getElementById("mouseEnable");
            //사각형 선택이 체크가 안되었을때!
            if(!mouseEnable.checked){
                startX = startY=0;
                endX = inW;
                endY= inH;
                rotateImage();
                return;
            }
            //사각형 체크됨.
            //마우스 이벤트 리스너 켜기
            onEventListener();
    }

 

 

 


<원본이미지 90도 회전>

알고리즘
결과화면

function image90(){   // 90도 회전
        // (중요!) 출력 이미지의 크기가 결정 ---> 알고리즘에 의존...
        outH=inH;
        outW=inW;
        // 출력 영상의 2차원 메모리 할당
        outImage = new Array(3);
        for(var m=0; m<3; m++){
            outImage[m] = new Array(outH);
        for(let n=0; n<outH; n++)
            outImage[m][n] = new Array(outW);
        }
            // **** 진짜 영상처리 알고리즘 *****
        for (var rgb=0; rgb<3; rgb++) {
            for(var i=0; i<inH; i++){
                for(var k=0; k<inW; k++){
                    if ((startX <= k && k <= endX) && (startY <= i && i <= endY)){
                        outImage[rgb][inW-k-1][i] = inImage[rgb][i][k];
                    }else{
                        outImage[rgb][i][k] = inImage[rgb][i][k];
                    }
            }
        }
    }
    displayImage();
}
        function image90_mouse(){
            var mouseCheck= document.getElementById("mouseEnable");
            //사각형 선택이 체크가 안되었을때!
            if(!mouseEnable.checked){
                startX = startY=0;
                endX = inW;
                endY= inH;
                image90();
                return;
            }
            //사각형 체크됨.
            //마우스 이벤트 리스너 켜기
            onEventListener();
        }

 


<원본이미지 반시계방향 회전>

알고리즘
결과화면

 function spinImage() {
        let degree = parseFloat(prompt("회전각도를 입력하시오", "45"));
        let radian = (degree * Math.PI) / 180.0;
        
        if(startX==0){
            outH = parseInt(Math.abs(Math.cos(radian) * inH) + Math.abs(Math.cos(Math.PI / 2 - radian) * inW));
        outW = parseInt(Math.abs(Math.cos(radian) * inW) + Math.abs(Math.cos(Math.PI / 2 - radian) * inH));

        outImage = new Array(3); //3면
        for (var m = 0; m < 3; m++) {
            outImage[m] = new Array(outH);
            for (let n = 0; n < outH; n++) 
                outImage[m][n] = new Array(outW);
        }

        let xd, yd;

        let cx = parseInt(outH / 2);
        let cy = parseInt(outW / 2);

        for (var rgb = 0; rgb < 3; rgb++) {
            for (let i = 0; i < outH; i++) {
                for (let k = 0; k < outW; k++) {
                    xd = parseInt(Math.cos(radian) * (i - cx) + Math.sin(radian) * (k - cy) + (cx / outH) * inH);
                    yd = parseInt(-Math.sin(radian) * (i - cx) + Math.cos(radian) * (k - cy) + (cy / outW) * inW);
                    
                    if (0 <= xd && xd < inH && 0 <= yd && yd < inW)
                        outImage[rgb][i][k] = inImage[rgb][xd][yd];
                    else outImage[rgb][i][k] = 255;
              
                }
            }
        }
    }
        else{
            outH = inH;
            outW = inW;

            outImage = new Array(3); //3면
            for (var m = 0; m < 3; m++) {
                outImage[m] = new Array(outH);
                for (let n = 0; n < outH; n++) 
                    outImage[m][n] = new Array(outW);
            }

            let xd, yd;

            let cx = parseInt(outH / 2);
            let cy = parseInt(outW / 2);

            for (var rgb = 0; rgb < 3; rgb++) {
                for (let i = 0; i < outH; i++) {
                    for (let k = 0; k < outW; k++) {
                        xd = parseInt(Math.cos(radian) * (i - cx) + Math.sin(radian) * (k - cy) +cx);
                        yd = parseInt(-Math.sin(radian) * (i - cx) +Math.cos(radian) * (k - cy) +cy);

                        if((startX <= k && k< endX )&&(startY <=i && i<endY)){
                            if (0 <= xd && xd < inH && 0 <= yd && yd < inW)
                                outImage[rgb][i][k] = inImage[rgb][xd][yd];
                            else outImage[rgb][i][k] = 255;
                        }

                        else{
                            outImage[rgb][i][k] = inImage[rgb][i][k];
                        }

                    }
                }
            }
        }
        
        displayImage();
      }
      function spinImage_mouse(){
        var mouseCheck= document.getElementById("mouseEnable");
            //사각형 선택이 체크가 안되었을때!
            if(!mouseEnable.checked){
                startX = startY=0;
                endX = inW;
                endY= inH;
                spinImage();
                return;
            }
            //사각형 체크됨.
            //마우스 이벤트 리스너 켜기
            onEventListener();
      }