본문 바로가기

OpenCV없는 영상처리

화소 점 처리

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


< 원본 이미지 밝게(더하기) 처리하기>

원본이미지에 값을 더해서 이미지의 픽셀값을 밝게 변경 후

변경된 픽셀 값이 255를 넘으면 255값으로 변경한다.

그림과 같이 inImage+value를 한 값이 255값을 넘으면 그 픽셀의 값을 255로 변경해준다.

알고리즘
결과화면

//입력 받은 숫자 만큼 밝기를 올리는 함수
function lightImage(){
                //출력되는 사진의 크기는 변하지 않는다
                outH=inH;
                outW=inW;
                //출력할 배열 생성
                outImage=new Array(outH);
                for(let i=0;i<outH;i++){
                    outImage[i]=new Array(outW);
                }
                //얼마나 밝게 할 것인지 값을 입력받는다.(value)
                let value = parseInt(prompt("숫자를 입력하세요","100"))
                //inImage의 밝기를 올려 outImage에 대입한다.
                for(let i=0;i<inH;i++){
                    for(let k=0;k<inW;k++){
                        //만약 입력받은 값을 더했을때 사진이 나타낼수있는 최대 밝기인 255를 넘는다면
                        //255로 정한다.
                        if(inImage[i][k]+value>255)
                            outImage[i][k]=255;
                        //255를 넘지 않는다면 밝기만 더해주면 된다.   
                        else
                            outImage[i][k]=inImage[i][k]+value;
                    }
                }
                //밝기를 바꾸고 출력이미지를 다시 원본이미지(inImage)에 넣어준다.
                //다음번에 밝기를 바꾸면 누적해서 계속 밝아지게 된다.
                for(i=0;i<inH;i++){
                    for(k=0;k<inW;k++){
                        inImage[i][k]=outImage[i][k];
                }
                //출력함수
                displayImage();
            }
        }

 


<원본 이미지 어둡게(빼기) 처리하기>

원본이미지에 값을 빼서 이미지의 픽셀값을 어둡게 변경 후

변경된 픽셀 값이 0이하가 되면 0으로 변경한다

그림과 같이 inImage-value를 한 값이 0값이하가 되면 그 픽셀의 값을 0으로 변경해준다.

알고리즘
결과화면

//입력받은 값만큼 어둡게 만드는 함수
        function darkImage(){
                //출력되는 사진의 크기가 변하지 않는다
                outH=inH;
                outW=inW;
                //출력할 배열 생성
                outImage=new Array(outH);
                for(let i=0;i<inH;i++)
                    outImage[i]=new Array(outW);
                //얼마나 어둡게 할 것인지 입력 받는다.(value)
                let value = parseInt(prompt("숫자를 입력하세요","100"));
                //inImage(원본이미지)를 어둡게 하여 outImage(출력할 이미지)에 대입한다.
                for(let i=0;i<inH;i++){
                    for(let k=0;k<inW;k++){
                        //값을 빼주었을때 원본이미지의 값이 이미지의 최소 밝기인 0보다 작아진다면
                        //출력이미지의 값을 0으로 설정한다.
                        if(inImage[i][k]-value<0)
                            outImage[i][k]=0;
                        //0보다 작아지지 않는 값들은 그대로 대입한다.
                        else
                            outImage[i][k]=inImage[i][k]-value;
                    }
                }
                //밝기를 바꾸고 원본이미지에 대입한다.
                //다음번 어둡게할때 누적해서 어둡게 하기 위함
                for(i=0;i<inH;i++){
                    for(k=0;k<inW;k++){
                        inImage[i][k]=outImage[i][k];
                    }
                }
                //출력함수
                displayImage();
            }

 

 


<원본 이미지 흑백 처리하기(127을 기준으로)>

픽셀이 가질수 있는 값의 범위는 0~255이고 흑백이미지는 0과 255의 값만 가진다.

픽셀이 가질 수 있는 값의 중앙 값인 127을 기준으로 127보다 작으면 0, 크면 255로 값을 설정한다.

하지만 흑백으로 처리할때 127을 기준으로 처리하면 결과 이미지를 보면 하늘부분에 밝게 나와야하는 부분이 어둡게 칠해진다.

그래서 시도해 볼수 있는 다른 방법은 평균값을 기준으로 흑백 처리하는 것이다.

 

알고리즘
결과화면

//흑백이미지 127을 기준으로 변경
            function image127(){
                //이미지의 크기는 변하지 않음
                outH=inH;
                outW=inW;
                //출력할 배열 생성
                outImage=new Array(outH);
                for(let i=0;i<outH;i++)
                    outImage[i]=new Array(outW);
                //127을 기준으로 한 흑백이미지로 변경, 흑: 0 ,백: 255
                for(let i=0;i<outH;i++){
                    for(let k=0;k<outW;k++){
                        //원본이미지가 127보다 크다면 최대 밝기인 255로 설정(백)
                        if(inImage[i][k]>127)
                            outImage[i][k]=255;
                        //원본이미지가 127보다 작다면 최소 밝기인 0으로 설정(흑)
                        else
                            outImage[i][k]=0;
                    }
                }
                //흑백을 바꿔서 원본이미지를 바꾼다.
                //다른 함수를 클릭했을때 흑백으로 바뀐 사진이 변한다.
                //있어도 되고 없어도 되고
                for(i=0;i<inH;i++){
                    for(k=0;k<inW;k++){
                        inImage[i][k]=outImage[i][k];
                    }
                }
                //출력함수
                displayImage();
            }

 

 


<원본이미지 흑백 처리하기(픽셀의 평균 값을 기준으로)>

이미지의 평균값을 기준으로 처리하는 방법은 일단 이미지의 픽셀에 속해 있는 값들을 모두 더해서 이미지의 크기로 나눠 이미지의 픽셀들의 평균값을 구해준다.

아래 그림과 같이 평균값이 168이라고 하면 168보다 크면 255로 초기화하고 작으면 0으로 초기화 한다.

이 역시 평균 값에서 오류가 발생할 수 있다

만약 픽셀 값들에서 눈에 띄게 평균을 웃도는 값이 있다면 그로 인해 평균 값이 높아져서 평균 값이라는 게 그 이미지의 보편적인 중간 값을 지니지 못할 수 있다.

이 역시 뚜렷한 흑백이미지으로의 변경에는 사용할 수 없다.

이의 해결책으로는 픽셀의 중앙값을 이용해 흑백이미지로 변경하는 방법이 있다.

 

예를 들면 이런 느낌 

같은 반의 용돈 평균 구하고자 할 때 1명을 제외한 대다수가 10만원 이하인데 누구 한명이 2억의 용돈을 받는다면 평균이 2000만원이 되고 이 값은 그반의 보편적인 용돈의 평균을 대표할 수 없다.

알고리즘
결과화면

//픽셀의 평균값을 기준으로 흑백이미지로 변경하는 함수
            function avgImage(){
                //출력이미지 크기는 같다.
                outH=inH;
                outW=inW;
                //출력할 배열 생성
                outImage=new Array(outH);
                for(let i=0;i<outH;i++)
                    outImage[i]=new Array(outW);
                //원본이미지의 픽셀의 평균 값을 구한다.
                //hap은 원본이미지의 픽셀 값을 모두 더하는 변수
                //cnt는 원본이미지의 픽셀의 수를 구하는 변수
                //avg는 hap/cnt로 픽셀의 평균값을 저장할 변수
                let hap=0,avg,cnt=0;
                //픽셀들을 더하고 픽셀의 수를 센다
                for(let i=0;i<inH;i++){
                    for(let k=0;k<inW;k++){
                        hap+=inImage[i][k];
                        cnt++;//inH**2의 값과 같겠다 정사각형이니까
                    }
                }
                //원본이미지의 픽셀의 평균 값
                avg=parseInt(hap/cnt);
                //평균값을 기준으로 흑백이미지로 변환
                for(i=0;i<inH;i++){
                    for(k=0;k<inW;k++){
                        //평균 값보다 크다면 최대밝기인 255로 설정(백)
                        if(inImage[i][k]>avg)
                            outImage[i][k]=255;
                        //평균값보다 작다면 최소밝기인 0으로 설정(흑)
                        else
                            outImage[i][k]=0;
                    }
                }
                //원본이미지를 바꿔주는 이중for문은 넣지 않았다
                //출력함수
                displayImage();
            }

 

 


<원본 이미지 흑백 처리하기(픽셀의 중앙 값을 기준으로)>

-출력이 안된다.. 수정 필요!

 

픽셀들을 이미지 크기만큼의 크기로 선언한 배열에 넣은 다음 그 배열을 작은 것부터 큰 것 순으로 정리한후

 그 배열의 인덱스의 중앙에는 이미지 픽셀의 중앙 값이 들어 있게 된다.

배열의 중앙 픽셀값을 기준으로 픽셀의 중앙값보다 크면 255로 초기화하고 작으면 0으로 초기화 한다.

 

정렬을 할때는 효율적인 알고리즘을 쓰는 것이 중요하다.

이 코드는 맨처음에는 적당한 시간내에는 출력이 되었으나 나중되니 시간이 오래 걸리면서 안나온다...

알고리즘

//흑백처리를 중앙값을 기준으로 한 함수
            //이 함수는 for문을 많이 돌려서 속도가 늦는다.
            //해결방법: 정렬 알고리즘 변경
            function bwMiddleImage(){
                //원본이미지와 크기는 같다.
                outH=inH;
                outW=inW;
                //출력할 배열 생성
                outImage=new Array(outH);
                for(let i=0;i<outW;i++)
                    outImage[i]=new Array(outW);
                //원본이미지의 픽셀 값들을 저장할 1차원 배열(tmpImage) 생성
                //배열의 크기는 모든 픽셀 값들을 저장해야 하므로 
                //이미지 전체크기(512x512 혹은 256x256)로 한다
                let tmpImage= new Array(outH**2);
                //배열의 크기를 반복문에 직접입력하는 방법도 있지만
                //컴퓨터가 알아서 세어주면 그 변수를 내가 쓰려고 
                //cnt라는 배열크기를 저장할 변수를 만들었다.
                let cnt =0;
                //일차원배열에 이미지 픽셀값 모두 저장
                for(i=0;i<outH;i++){
                    for(k=0;k<outW;k++){
                        tmpImage[cnt++]=inImage[i][k];
                    }
                }
                //일차원배열의 픽셀 값들을 크기 순서대로 정렬
                let temp;
                for(i=0;i<cnt-1;i++){
                    for(k=i+1;k<cnt;k++){
                        if(tmpImage[i]>tmpImage[k]){
                            temp=tmpImage[i];
                            tmpImage[i]=tmpImage[k];
                            tmpImage[k]=temp;
                        }
                    }
                }
                //정렬된 일차원 배열의 정중앙에는 이미지의 픽셀 중앙값이 들어있다.
                //flag에 일차원배열의 중앙 값을 저장한다.(흑백 기준)
                let flag = tmpImage[outH**2/2];
                for(i=0;i<outH;i++){
                    for(k=0;k<outW;k++){
                        //일차원배열의 중앙값보다 크다면 255로 설정(백)
                        if(inImage[i][k]>flag)
                            outImage[i][k]=255;
                        //중앙값보다 작다면 0으로 설정(흑)
                        else
                            outImage[i][k]=0;
                    }
                }
                //출력함수
                displayImage();

            }

 

 


<원본이미지 파라볼라 캡 처리하기(밝은 곳을 입체화)>

파라볼라 캡은 이미지의 밝은 곳을 입체화하는 이미지 처리 효과 이다.

위로 볼록한 함수로 0와 255에 가까워질수록 가중치 값이 감소한다.

 

 

알고리즘
결과화면

//이미지를 파라볼라 캡하는 함수
            //어두운 곳을 입체화한다.
            function paraCapImage(){
                //출력이미지의 크기는 원본이미지와 같다.
                outH=inH;
                outW=inW;
                //출력할 배열생성
                outImage=new Array(outH);
                for(i=0;i<outH;i++)
                    outImage[i]=new Array(outW);
                //원본이미지를 파라볼라 캡 한것을 출력이미지에 저장
                for(let i=0;i<outH;i++){
                    for(let k=0;k<outW;k++){
                    	//파라볼라 캡 변환 공식(다른 프로그래밍 언어)
                        //new_pixel = 255.0 - 255.0 * (( double(x)/128.0 - 1.0)^2); 
                        outImage[i][k]=255- (255)*Math.pow((inImage[i][k]/128-1),2);
                    }
                }
                //출력함수
                displayImage();
            }

 

 


<원본이미지 파라볼라 컵 처리하기(어두운 곳을 입체화)>

파라볼라 컵은 어두운 곳을 입체화하는 이미지 처리효과이다.

아래로 볼록한 함수이고 0과 255로 갈수록 가중치가 높아진다.

 

알고리즘
결과화면

//이미지를 파라볼라 컵하는 함수
            //밝은 곳을 입체화한다.
            function paraCupImage(){
                //출력이미지의 크기는 원본이미지와 같다
                outH=inH;
                outW=inW;
                //출력할 배열 생성
                outImage=new Array(outH);
                for(i=0;i<outH;i++)
                    outImage[i]=new Array(outW);
                //원본이미지를 파라볼라 컵 변환 한 것을 출력이미지에 저장
                for(let i=0;i<outH;i++){
                    for(let k=0;k<outW;k++){
                        //파라볼라 컵 변환 공식(다른 프로그래밍 언어)
                        //new_pixel = 255.0 * (( double(x)/128.0 - 1.0)^2); 
                        outImage[i][k]=Math.pow((inImage[i][k]/128-1),2)*255;
                    }
                }
                //출력함수
                displayImage();
            }

 

 


<원본이미지 감마 처리하기 >

모니터의 출력은 입력신호가 커질수록 명암이 높고 밝기가 어두워지는 경향이 있어

인간의 눈에 왜곡없이 보이게 하기 위해서 감마보정 후 모니터에 출력할 때 사용한다.

여기서 왜곡없이 보이게란?

모니터의 감마값을 감마 값으로 나눴을때 1의 값을 가지도록 하여 y=x함수가 되도록 하는 것이다.

감마값은 모니터의 감마값에 따라 결정된다 모니터의 감마 값이 2.5이면 나눠주는 감마 값도 2.5가 되는 것이다.

 

알고리즘
결과화면

			//이미지 감마 변환 함수
            //감마변환 : 이미지를 밝아지거나 어두워지게 한다.
            //모니터은 출력은 입력신호가 커질수록 명암이 높고 밝기가 어두워지는 경향이 있어
            //인간의 눈에 왜곡없이 보이게 하기 위해서 감마보정후 모니터에 출력할때 사용한다.
            function gammaImage(){
                //원본이미지 크기 그대로
                outH=inH;
                outW=inW;
                //출력배열을 생성
                outImage=new Array(outH);
                for(let i=0;i<outH;i++)
                    outImage[i]= new Array(outW);

                let value = parseInt(prompt("감마값입력","1.5"));
                //출력결과를 보면 감마 값이 0보다 크면 어두워지고 0보다 작으면 밝아진다.
                if(value<0)
                    value=1/(1-value);
                else
                    value+=1;
                //감마 변환
                for(let i=0;i<outH;i++){
                    for(let k=0;k<outW;k++){
                        //감마변환공식(다른 프로그래밍 언어)
                        //double gamma = 1.0 / m_dGamma;
                        //arrPow[n] = (BYTE)(pow(n/255.0, gamma)*255 + 0.5);
                        outImage[i][k]=parseInt((inImage[i][k]/255)**(value)*255+0.5);
                    }
                }
                //출력함수
                displayImage();
            }

 

 


<원본 이미지 밝게(곱하기) 처리하기>

원본이미지에 곱하고 그 값이 픽셀의 값이 최대값인 255값을 넘으면 그 값을 255로 변경해준다.

이미지를 밝게 곱하기 하는 방법은 더하기 하는 방법과 유사하다

알고리즘
결과화면

//이미지에 값을 곱하는 함수
            //더하기 함수와 연산자 쓰는 것만 다르다
            function gopImage(){
                outH=inH;
                outW=inW;

                outImage=new Array(outH);
                for(let i=0;i<outW;i++)
                    outImage[i]=new Array(outW);

                value=parseInt((prompt("곱할 값을 입력하시오","2")));
                for(i=0;i<outH;i++){
                    for(k=0;k<outH;k++){
                        //곱한 값이 255보다크면 255로 설정 
                        if(inImage[i][k]*value>255)
                            outImage[i][k]=255;
                        //곱한 값이 255를 넘지 않으면 value값을 곱한 값을 출력 배열에 대입한다.
                        else
                            outImage[i][k]=inImage[i][k]*value;
                    }
                }
                //출력함수
                displayImage();
            }

 

 


<원본이미지 어둡게(나누기) 처리하기>

원본이미지를 입력받은 값으로 나누고 그 값이 최소값인 0이하가 되면 그 값을 0으로 변경해준다.

이미지를 어둡게 나누기하는 방법은 빼기하는 방법과 유사하다.

알고리즘
결과화면

//이미지값을 나누는 함수
            //빼기 함수의 연산자 쓰는 것만 다르다.
            function divImage(){
                outH=inH;
                outW=inW;

                outImage=new Array(outH);
                for(let i=0;i<outW;i++)
                    outImage[i]=new Array(outW);

                value=parseInt((prompt("나눌 값을 입력하시오","2")));
                for(i=0;i<outH;i++){
                    for(k=0;k<outH;k++){
                        //나눈 값이 0보다 작다면 0으로 설정
                        if(inImage[i][k]/value<0)
                            outImage[i][k]=0;
                        //나눈 값이 0과 같거나 크면 나눈 값을 출력배열에 대입
                        else
                            outImage[i][k]=inImage[i][k]/value;
                    }
                }
                //출력함수
                displayImage();
            }

 

 

흑백 이미지 중앙값에서 배열 정렬 알고리즘 바꾸기 필요!

'OpenCV없는 영상처리' 카테고리의 다른 글

영상처리의 전처리부  (0) 2022.09.12
히스토그램 처리  (0) 2022.09.11
화소영역처리  (0) 2022.09.11
기하학처리  (0) 2022.09.11
인공지능과 영상처리  (0) 2022.09.11