지금까지 배운 내용을 토대로 10가지 정도의 이미지 프로세싱 알고리즘을 opencv로 구현하여 매트랩에서 제공하는 함수와의 차이를 확인해보자

 

  • Quantization

  • 매트랩 코드
1
2
3
4
5
6
7
8
clear; clc;
x=imread('boat.png');
f=floor(double(x)/32);
q1=uint8(f*32);
subplot(1,2,1), imshow(x), subplot(1,2,2), imshow(q1);
 
[psnr, snr] = psnr(x,q1);
psnr 
cs

 

  • opencv 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <Windows.h>
#include "opencv2/opencv.hpp"
#include <cmath>
 
using namespace cv;
 
void ft_color_depth_reduction(Mat &image, int labels){
 
    int h = image.rows; // height (영상의 높이)
    int w = image.cols; // width (영상의 너비)
 
    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            // 0-255 level (gray image) 인 경우 :
            if (image.channels() == 1)
            {
                uchar data = image.at<uchar>(y, x);
                data = data / labels * labels + labels / 2;
                image.at<uchar>(y, x) = data;
            }
            // RGB level (color image) 인 경우 :
            else if (image.channels() == 3)
            {
                Vec3b colVal = image.at<Vec3b>(y, x);
                colVal[2= colVal[2/ labels * labels + labels / 2;
                colVal[1= colVal[1/ labels * labels + labels / 2;
                colVal[0= colVal[0/ labels * labels + labels / 2;
                image.at<Vec3b>(y, x) = colVal;
            }
        }
    }
}
void main()
{
    Mat srcimage = imread("boat.png"-1); // 변환할 영상
 
    if (!srcimage.data)
    {
        printf("No Image Found\n");
        return;
    }
    namedWindow("Original Image", WINDOW_AUTOSIZE);
    imshow("Original Image", srcimage);
    Mat outimage = srcimage.clone();
    int num = 32;
    ft_color_depth_reduction(outimage, num);
    imshow("Output Image", outimage);
    waitKey(0);
    destroyAllWindows();
}
cs
  •  결과 사진 비교

    1. 매트랩

   

2.   opencv

  • 이미지 회전

  • 매트랩 코드

  • opencv 코드

  • 결과비교

    1. 매트랩

 

 2.   opencv

 

 

Opencv matlab을 이용하여 이미지의 회전을 하였습니다. 회전은 반시계방향으로 45도를 회전하였습니다. 회전 후의 이미지는 두 opencv matlab은 차이가 있었습니다. 눈으로 봐도 명확히 알 수 있던 것이 opencv를 이용하여 이미지는 사진의 가장자리는 깨끗이 나온 것을 알 수 있습니다. 허나 matlab의 경우에는 aliasing 이 발생한다는 것을 알 수 있었습니다. 이는 설정에 따른 차이때문입니다. opencv에서는 cv2DRotationMatrix()를 이용하였습니다.

매트랩의 경우에는 imrotate()를 사용하였습니다.

Imrotate( A, angle ) <- A : image,

  • fft -> ifft

  • 매트랩 코드

1
2
3
4
5
ca=imread('Matlab_Image/lenna.jpg');
%ca = rgb2gray(ca);
ca_F=fft2(double(ca));
ca_FI=ifft2(ca_F);
subplot(1,2,1),imshow(ca),subplot(1,2,2),imshow(ca_FI,[]);
cs

 

  • opencv 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
 
int main()
{
    Mat I = imread("lenna.jpg", CV_LOAD_IMAGE_GRAYSCALE);
    if (I.empty())
    return -1;
 
    Mat padded;                            //expand input image to optimal size
    int m = getOptimalDFTSize(I.rows);
    int n = getOptimalDFTSize(I.cols); // on the border add zero values
    copyMakeBorder(I, padded, 0, m - I.rows, 0, n - I.cols, BORDER_CONSTANT, Scalar::all(0));
 
    Mat planes[] = { Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F) };
    Mat complexI;
    merge(planes, 2, complexI);         // Add to the expanded another plane with zeros
 
    dft(complexI, complexI);            // this way the result may fit in the source matrix
 
    // compute the magnitude and switch to logarithmic scale
    // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2))
    split(complexI, planes);                   // planes[0= Re(DFT(I), planes[1= Im(DFT(I))
 
    magnitude(planes[0], planes[1], planes[0]);// planes[0= magnitude
    Mat magI = planes[0];
 
    magI += Scalar::all(1);                    // switch to logarithmic scale
    log(magI, magI);
 
    // crop the spectrum, if it has an odd number of rows or columns
    magI = magI(Rect(00, magI.cols & -2, magI.rows & -2));
 
    // rearrange the quadrants of Fourier image  so that the origin is at the image center
    int cx = magI.cols / 2;
    int cy = magI.rows / 2;
 
    Mat q0(magI, Rect(00, cx, cy));   // Top-Left - Create a ROI per quadrant
    Mat q1(magI, Rect(cx, 0, cx, cy));  // Top-Right
    Mat q2(magI, Rect(0, cy, cx, cy));  // Bottom-Left
    Mat q3(magI, Rect(cx, cy, cx, cy)); // Bottom-Right
 
    Mat tmp;                           // swap quadrants (Top-Left with Bottom-Right)
    q0.copyTo(tmp);
    q3.copyTo(q0);
    tmp.copyTo(q3);
 
    q1.copyTo(tmp);                    // swap quadrant (Top-Right with Bottom-Left)
    q2.copyTo(q1);
    tmp.copyTo(q2);
 
 
    normalize(magI, magI, 01, CV_MINMAX); // Transform the matrix with float values into a
    //normalize(phaseVals, phaseVals, 01, CV_MINMAX);
    // viewable image form (float between values 0 and 1).
 
    imshow("Input Image", I);    // Show the result
    imshow("Spectrum Magnitude", magI);
    //waitKey();
 
    //calculating the idft
    cv::Mat inverseTransform;
    cv::dft(complexI, inverseTransform, cv::DFT_INVERSE | cv::DFT_REAL_OUTPUT);
    normalize(inverseTransform, inverseTransform, 01, CV_MINMAX);
    imshow("Reconstructed", inverseTransform);
    waitKey();
 
    return 0;

cs

 

  • 결과 비교

    1. 매트랩

2.   opencv

 

 

  • Gaussian

  •  매트랩 코드

1
2
3
4
5
6
7
8
9
10
11
tic
 
origin = imread('engineer.tif');
noise_img = imnoise(origin,'gaussian',0,0.02);
filt = fspecial('average',[5,5]);
result = filter2(filt,noise_img);
 
imshow(noise_img);
figure(),imshow(result/255);
 
toc
cs
  • opencv 코드

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <time.h>
 
 
IplImage* GaussianNoiseCreate(IplImage *img, int std);
 
>> 가우시안 노이즈를 생성하는 함수의 프로토타입 선언
 
void main() {
    clock_t start, end;
    start = clock();    
    double result;
    
    IplImage *srcImage = cvLoadImage("engineer.tif"-1);
>> 가우시안 노이즈를 입히고 제거하기 위해서 이미지를 불러옵니다.
>> cvLoadImage(“원하는 이미지파일명”,-1);로 Load합니다.
    
 
    //가우시안 잡음 이미지 생성
    //가우시안 잡음 : 가우시안 밀도 함수를 갖는 잡음 (표준편차가 클수록 잡음이 많이 포함됨)
    IplImage *noiseImage = GaussianNoiseCreate(srcImage, 20);
 
>> 작성하는 GaussinNoiseCreate 함수를 통해 원본이미지를 Gaussian 노이즈를 입힌다. 이때 두번째 파라미터 값인 표준편차가 클수록 많은 양의 노이즈를 씌워줄수 있다.
>> srcImage에 가우시안 노이즈를 발생시켜서 noiseImage에 넣어준다.
 
    IplImage* resultImage = cvCreateImage(cvGetSize(noiseImage), IPL_DEPTH_8U, 1);
 
    cvSmooth(noiseImage, resultImage, CV_BLUR, 55);
 
>> 가우시안 노이즈를 평균 필터링을 통해 제거한다 , 필터의 크기는 5x5로 설정되었으며, 노이즈의 양이 많으면 더 큰 크기의 필터의 사용이 필요하며, 수행속도가 느려진다.반대로 노이즈의 크기가 작으면 작은 크기의 필터의 사용이 필요하며, 수행속도가 빨라진다. 따라서 노이즈의 크기를 보고서 알맞은 필터크기를 선정해주는 것이 중요하다. 
 
    end = clock();
    result = (double)(end - start);
    printf("수행시간은 %f초입니다.", result/1000);
    //create window
    cvNamedWindow("source", CV_WINDOW_AUTOSIZE);
    cvNamedWindow("remove", CV_WINDOW_AUTOSIZE);
    //show image
    cvShowImage("source", noiseImage);
    cvShowImage("remove", resultImage);
 
    cvWaitKey(0);
 
    //release image
    cvReleaseImage(&noiseImage);
    cvReleaseImage(&resultImage);    
}
 
//가우시안 잡음 생성 함수
 
IplImage* GaussianNoiseCreate(IplImage *img, int std) {
    int height = img->height;
    int width = img->width;
    int step = img->widthStep;
    uchar* data = (uchar*)img->imageData;
 
    int imgSize = width * height *img->nChannels;
    time_t nowTime;
    srand(time(&nowTime));
 
    int r1, r2;
    double random1, random2, normal, stdNormal, tmp;
    do {
 
        r1 = rand() % width;
        r2 = rand() % height;
 
>> 가우시안 잡음 생성 함수에서 r1과 r2는 이미지에서 노이즈를 발생시킬 위치를 랜덤으로 정하는 것이다.
 
 
        random1 = (double)rand() / RAND_MAX;
        random2 = (double)rand() / RAND_MAX;
 
        stdNormal = sqrt(-2.0 * log(random1)) * cos(2 * 3.14159 * random2);
 
        normal = std * stdNormal;
 
>> std는 표준편차로 아래 if문을 통해 데이터 값의 범위를 0~255범위의 임의의 값으로 만들 때 사용한다.
 
        int index = r1 * step + r2;
        if (index >= imgSize) {
            index = imgSize - 1;
        }
 
        tmp = data[index] + normal;
 
        if (tmp < 0) { data[index] = 0; }
        else if (tmp > 255) { data[index] = 255; }
        else { data[index] = (unsigned char)tmp; }
 
        imgSize--;
    } while (imgSize > 0);
 
    return img;
}
cs
  • 결과비교 

    1. 매트랩

 

2.   opencv

 

검정색 출력창은 visual Open-CV로 가우시안 노이즈 생성 및 제거를 수행했을때의 시간 이고 하얀색 출력창은 Matlab에서 가우시안 노이즈 생성 및 제거를 수행했을때의 시간이다. Open-CVMatlab의 성능은 사람의 눈으로 구분하기에는 큰 차이를 구별할 수가 없는 수준이다.

하지만 수행시간에는 차이를 보였다. 0.4초정도가 Open-CV로 처리하였을 때 더빠른 속도처리를 볼수있었다.

또한 평균필터링을 통해서 노이즈 제거한 이미지에서 노이즈가 제거되었지만 노이즈 뿐만 아니라 원이미지의 성분도 잃어버려서 원본이미지와는 조금의 차이가 보인다.

이것은 Imgae Enhancement를 적용하여서 원이미지와 비슷하게 만들어주는 기법이 필요해보인다.

 

  • histogram equalization 

  •  매트랩 코드

  • opencv 코드

 

 

  •  결과비교

    1. opencv

2.   매트랩

 

 

  • Canny edge

  • 매트랩 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Origin_image=imread('eye.tif');
BW1 = edge(Origin_image,'Canny');
imshow(BW1);      title("Canny");
 
%% color
 
이 프로그램은 원본 이미지를 YCbCr 색 공간으로 변환하여 컬러 이미지의 가장자리를 찾습니다.
%eye.tif
%susan.tif
 
img=imread('susan.tif');
[x y z]=size(img);
if z==1
    rslt=edge(img,'canny');
elseif z==3
    img1=rgb2ycbcr(img);
    dx1=edge(img1(:,:,1),'canny');
    dx1=(dx1*256);
    img2(:,:,1)=dx1;
    img2(:,:,2)=img1(:,:,2);
    img2(:,:,3)=img1(:,:,3);
rslt=ycbcr2rgb(uint8(img2));
end
R=rslt;
imshow(R);      title("Canny");
cs
  • opencv 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv/cv.h"
#include <stdlib.h>
#include <stdio.h>
#include<time.h>
 
using namespace std;
 
void main()
{
    clock_t start, end;
    double result;
    IplImage* srcImage = cvLoadImage("susan.tif", CV_LOAD_IMAGE_GRAYSCALE);
    IplImage* cannyImage1 = cvCreateImage(cvGetSize(srcImage), IPL_DEPTH_8U, 1);
 
    if (srcImage == NULL)
        return;
    cvNamedWindow("cannyImage1", CV_WINDOW_AUTOSIZE); //window 화면 뛰우기
    start = clock();                
    cvCanny(srcImage, cannyImage1, 501003);
    end = clock();
    cvShowImage("CannyImage1", cannyImage1);
    
    cvWaitKey(0); 
    cvDestroyAllWindows();
    cvReleaseImage(&cannyImage1);
    
    result=(double)(end - start);
    printf("%f", result);
}
cs
  • 결과비교 

    1. 매트랩

 

 

                     2.   opencv

 

  • Salt & pepper noise

  •  매트랩 코드

1
2
3
4
5
6
7
8
9
tic
img = imread('cameraman.tif');
subplot(1,2,1);
imshow(img);
title('Original image')
subplot(1,2,2);
imshow(imnoise(img,'salt & pepper'));
title('salt & pepper');
toc
cs
  • opencv 코드 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<opencv2/opencv.hpp>
#include <iostream>
 
using namespace std;
using namespace cv;
 
void salt(cv::Mat &image, int n);
 
int main()
{
   cv::Mat image = cv::imread("house.jpg");
   salt(image, 1000);
   cv::namedWindow("my image");
   cv::imshow("my image", image);
   cv::waitKey(5000);
   return 1;
}
 
void salt(cv::Mat &image, int n) {
   for (int k = 0; k < n; k++) {
      int i = rand() % image.cols;
      int j = rand() % image.rows;
 
      if (image.channels() == 1) {
         image.at<uchar>(j, i) = 255;
      }
      else if (image.channels() == 3) {
         image.at<cv::Vec3b>(j, i)[0= 255;
         image.at<cv::Vec3b>(j, i)[1= 255;
         image.at<cv::Vec3b>(j, i)[2= 255;
      }
   }
}
cs
  • 결과비교

    1. 매트랩

 

                       2. opencv

같은 알고리즘을 수행한 결과 opencv가 매트랩보다 노이즈가 덜 한 것을 관찰할 수 있었습니다.

매트랩의 salt & pepper noise구현은 검은색과 흰색의 노이즈가 보이지만

opencv로 만들어본 nosie는 흰색의 노이즈만 관찰되었습니다.

  • sobel edge detect

  • 매트랩 코드

1
2
3
4
5
6
7
8
9
tic
og = imread('cameraman.tif');
subplot(1,2,1);
imshow(og);
title('Original image')
subplot(1,2,2);
imshow(edge(og,'sobel'));
title('sobel edge');
toc
cs
  • opencv 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "iostream"
#include <time.h>
#include <stdio.h>
using namespace cv;
using namespace std;
void main()
 
{
    clock_t start, end;
    start = clock();
    double result;
    Mat src1;
    src1 = imread("engineer.tif", CV_LOAD_IMAGE_COLOR);
    namedWindow("Original image", CV_WINDOW_AUTOSIZE);
    imshow("Original image", src1);
 
    Mat grey;
    cvtColor(src1, grey, CV_BGR2GRAY); // 그레이 영상으로 변환
    Mat sobelx, sobely;
    Sobel(grey, sobelx, CV_32F, 10); // Sobel 엣지 검출
    Sobel(grey, sobely, CV_32F, 01);
 
    namedWindow("vertical edge", CV_WINDOW_AUTOSIZE);
    imshow("vertical edge", sobelx);
    namedWindow("horizontal edge", CV_WINDOW_AUTOSIZE);
    imshow("horizontal edge", sobely);
 
    end = clock();        
    result = (double)(end - start);
    printf("time %f", result / 1000);
 
    waitKey(0);
 
}
cs
  • 결과 비교

    1. 매트랩

 

 경과시간 : 0.350917 sec

 

 2. opencv

 

 경과시간 : 0.108000 sec

 

matlab 같이 opencv 이용해 sobel edge detect 수행한 결과

opencv 이용한 것이 수행시간이 줄었습니다.

 

  • LOG(Laplacian of gaussian) 으로 엣지 검출

  • 매트랩 코드

1
2
3
4
5
6
7
8
I=imread('bacteria.tif');
 
figure(1);imshow(I);
 
BW=edge(I,'log'); 
LoG(가우스-라플라시안) 필터를 사용하여 I를 필터링한 후 영점교차를 찾아서 경계를 찾습니다.
 
figure(2);imshow(BW);
cs
  • opencv 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <opencv2\opencv.hpp>
#include <time.h>
#include <cstdio>
 
using namespace cv;
using namespace std;
 
int main() {
 
    clock_t beginend;
 
    Mat image = imread("bacteria.tif",0);
 
    CV_Assert(image.data);
 
    double sigma = 1.4;
    
    Mat dst1, gaus_img;
    // 시간측정 시작. 
    begin = clock();
 
    GaussianBlur(image, gaus_img, Size(99), sigma, sigma);
 
//가우시안 필터 씌우기
 
    Laplacian(gaus_img, dst1, -15);
 
//Laplacian을 통해 이차 미분을 할 수 있고, 따라서 edge를 검출 할 수 있다.
 
 
    end = clock();
 
    imshow("image", image);
    imshow("dst2- LOG_OpenCV", dst1);
    
 
 
    cout << "수행시간(초) : " << (double)(end - begin/ CLOCKS_PER_SEC << endl;
    waitKey();
 
 
    return 0;
 
}
cs
  • 결과비교

    1. 매트랩

 

2.   opencv

이번에는 특이하게 opencv의 수행시간이 더 걸렸는데 매트랩결과와 비교해보았을 때, opencv의 윤곽선이 더 진합니다.

Opencv는 비교적 디테일이 남아있는 모습을 보여줍니다.

이것을 없애고 싶다면 가우시안 필터를 더 키우면 될 것입니다.

  • DCT -> IDCT

  • 매트랩 코드

1
2
3
4
5
6
7
8
9
ca=imread('house.jpg');
ca = rgb2gray(ca);
ca_F=dct2(double(ca));
ca_F1=idct2(ca_F);
ca_F = uint8(ca_F);
ca_F1 = uint8(ca_F1);
subplot(1,3,1),imshow(ca),title('original image');
subplot(1,3,2),imshow(ca_F),title('DCT image');
subplot(1,3,3),imshow(ca_F1),title('IDCT image');
cs
  • opencv 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdlib.h>
#include <stdio.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
 
using namespace cv;
using namespace std;
 
int main()
{
    Mat image = imread("house.jpg"0); // grayscale
    Mat fimage;
    image.convertTo(fimage, CV_32F, 1.0 / 255);
    imshow("Original Image", image);
    Mat dimage;
    dct(fimage, dimage);
    
    imshow("DCT Image", dimage);
 
    Mat dimage2;
    dct(dimage, dimage2, DCT_INVERSE);
 
 
    imshow("IDCT", dimage2);
 
    waitKey();
 
 
    return 0;
}
cs

 

먼저 컬러 이미지 ‘house.jpg’gray이미지로 변환하고 dct2 함수를 이용해서 gray이미지를 이산코사인 변환 하고, idct2 함수를 이용해서 원본 이미지로 복원합니다.

  • 결과비교

    1. 매트랩

 

2.   opencv

OpenCV로 했을 때와 Matlab으로 했을 때 IDCT를 비교해보면 두 이미지의 차이가 심하지 않은 걸 볼 수 있습니다.

원본 이미지와 복원한 이미지를 비교해 보아도 달라진 점을 찾을 수 없는 것으로 보아 DCT의 손실율이 매우 작은 것을 확인 할 수 있었습니다.

'영상처리 실습' 카테고리의 다른 글

matlab wavelets toolbox  (0) 2018.12.06
노이즈 복원&엣지 검출 실습  (0) 2018.11.20

 

  • Haar wavelets : 쓸데없는 부분을 0으로 만드는 threshold를 하지 않음
  • Daubechies wavelets
  • Symlets
  • Biorthogonal wavelets : threshold 적용
  • 성능면에서는 Biorthogonal이 더 좋지만 수행시간 관점에서는 Haar가 더 빠르다
  • Filter 계수

  • db1은 Daubechies와 같음
  • db1은 필터 계수가 0.71, 즉 루트2에 해당하는 값이 나옴 -> 2개가 존재
  • db2는 필터 계수가 4개가 존재
  • 예제
  1. 4가지 인자는 각각 이미지의 값 -> 1scale
  2. input 이미지와 output 이미지의 값이 같아야 할 수도 있음
  3. LL1의 이미지를 다시 4등분 할 수 있음 -> 2scale
  4. 보통 LL쪽의 이미지를 scale한다
  5. 역방향 wavelet의 경우 4개의 요소들을 한꺼번에 줘야함
  6. idwt2애 4개의 요소를 넣은 값을 in_w1에 저장하여 이미지를 확인

  • dwt2의 인자에는 이미지와 어떤 방식으로 주파수 성분들을 나눌지를 넣는다
  • 2차원 DWT 개념 이해

  • Horizontal의 Edge성분이 HL에, vertical의 Edge성분이 LH에 나타난다
  • 즉 HH부분에는 대각선의 Edge성분이 나타난다

 

wavelet을 압축에 이용해 보자

  • wavelet의 LL부분만 사용한다면 4등분된 성분중에 1개만 사용하므로 1/4의 압축이 이루어진다
  • 여기서 다시 한 번 wavelet을 사용한다면 8배의 압축이 이루어지는 것이다
  • HL(Horizontal)과 LH(vertical)값의 제곱의 합의 제곱근으로 edge를 찾을 수 있다
  • 고주파(HH)부분을 적당히 없애준다면 noise제거에도 사용 가능하다

실습

  • haar와 Daubechies의 결과값 비교
    • 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
%% The Daubechies Wavelets
clear; clc;
c=imread('cameraman.tif');
figure, imshow(c);
dwtmode('per');
[LL1, LH1, HL1, HH1] = dwt2(c,'db2');
w1 = [LL1, LH1; HL1, HH1];
figure, imshow(mat2gray(w1));
[LL2, LH2, HL2, HH2] = dwt2(LL1, 'db2');
w2LL = [LL2, LH2; HL2, HH2];
w2 = [w2LL, LH1; HL1, HH1];
figure, imshow(mat2gray(w2));
%% 복구
in_w1LL = idwt2(LL2, LH2, HL2, HH2,'db2'); 
in_w1 = [in_w1LL, LH1; HL1, HH1];
figure, imshow(mat2gray(in_w1));
in_v = idwt2(in_w1LL, LH1, HL1, HH1, 'db2');
figure, imshow(mat2gray(in_v));
%% haar
clear; clc;
c=imread('cameraman.tif');
figure, imshow(c);
dwtmode('per');
[LL1, LH1, HL1, HH1] = dwt2(c,'haar');
w1 = [LL1, LH1; HL1, HH1];
figure, imshow(mat2gray(w1));
[LL2, LH2, HL2, HH2] = dwt2(LL1, 'haar');
w2LL = [LL2, LH2; HL2, HH2];
w2 = [w2LL, LH1; HL1, HH1];
figure, imshow(mat2gray(w2));
%% 복구
in_w1LL = idwt2(LL2, LH2, HL2, HH2,'haar'); 
in_w1 = [in_w1LL, LH1; HL1, HH1];
figure, imshow(mat2gray(in_w1));
in_v = idwt2(in_w1LL, LH1, HL1, HH1, 'haar');
figure, imshow(mat2gray(in_v));
cs
    • haar -> wavelet 1scale -> 2scale

  • haar -> 복구 2scale -> 1scale

  • Daubechies -> 1 scale -> 2 scale

  • Daubechies 복원 -> 2scale -> 1scale

  • PSNR의 경우는 threshlod값에 따라 값이 달라질 수 있다

 

  • DCT 기반 압축에서 Blook artifact현상을 없앨 수 있다 -> 압축률은 DCT가 더 우수
    •  Blook artifact : 나눈 블럭 사이에 경계선이 나타나는 현상

 

  • 1scale 후 LL성분을 0으로 만들고 inverse하면 edge성분만 검출됨

  • denoising : 고주파 성분을 제거

이미지 노이즈 씌우기

 

1. Pepper and salt noise

 

 

1
2
3
origin = imread('Matlab_Image/lenna.jpg');
PSnoise = imnoise(origin,'salt & pepper');
imshow(PSnoise);
cs

 

2. Gaussian noise

 

 

1
2
3
origin = imread('Matlab_Image/lenna.jpg');
Gnoise = imnoise(origin,'gaussian');
imshow(Gnoise);
cs

  

노이즈 이미지 복원

 

1. Restore Pepper and salt noise

 

 

1
2
R_PSnoise = medfilt2(PSnoise);
imshow(R_PSnoise);
cs

   

2. Restore Gaussian noise

 

 

1
2
3
4
5
6
7
8
s = size(origin);
t_gq10 = zeros(s(1),s(2),10);
for i=1:10 
    t_ga10(:,:,i)=imnoise(origin,'gaussian'); 
end
t_ga10_av=mean(t_ga10,3); 
t_ga10_av=uint8(t_ga10_av);
imshow(t_ga10_av);
cs

 

결과

 

1. 복원 이미지와 원본 이미지 비교

 

1) Pepper and salt noise

 

 

1
2
3
4
5
6
subplot(1,2,1);
imshow(origin);
title('Origin');
subplot(1,2,2);
imshow(R_HSnoise);
title('Restore Peper&Salt noise');
cs
 

2) Gaussian noise

 

1
2
3
4
5
6
 subplot(1,2,1);
 imshow(origin);
 title('Origin');
 subplot(1,2,2);
 imshow(t_ga10_av);
 title('Restore Gaussian noise');
cs

 

2. 원본 이미지와의 PSNR 계산

>직접 작성한 코드와 Matlab 라이브러리 결과 비교

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function PSNR = MY_PSNR(origin,second)
    origin = double(origin);
    second = double(second);
    
    m=length(origin(1,:)); %세로 길이
    n=length(origin(:,1)); %가로 길이
    temp = 0;
 
    for i=1:m
        for j=1:n
            temp = temp + (origin(i,j) - second(i,j))^2;
        end
    end
    
    MSE = temp/(m*n);
    
    PSNR = 20*log10(255/sqrt(MSE));
    
end
cs

 

1) 작성한 PSNR 계산 함수2) Matlab 라이브러리와 결과 비교 Pepper&Salt noise

 

1
2
MYPSNR = MY_PSNR(origin,PSnoise) %내가 만든 함수
LIBPSNR = psnr(origin,PSnoise) %매트랩 라이브러리 함수
cs

 

 

 

3) Matlab 라이브러리와 결과 비교 Gaussian noise

 

1
2
MYPSNR = MY_PSNR(origin,t_ga10_av) %내가 만든 함수
LIBPSNR = psnr(origin,t_ga10_av) %매트랩 라이브러리 함수
cs

 

 

 

 

엣지 검출 알고리즘

 

1. 소벨 엣지(직접 구현)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
%% 소벨 엣지 구현
clear; clc;
origin = imread('Matlab_Image/house.jpg');
 
SBMx = [-1 0 1;-2 0 2;-1 0 1]; %수직
SBMy = [-1 -2 -1;0 0 0;1 2 1]; %수평
 
%h = fspecial('gaussian',[5 5]);
 
originA = imgaussfilt(origin);
 
SBIv = abs(filter2(SBMx,originA));
SBIh = abs(filter2(SBMy,originA));
 
SBIS = SBIv + SBIh;
 
imshow(SBIS/255>0.7); %threshold
cs

 

2. 소벨 엣지(Matlab 라이브러리)

 

1
figure,imshow(edge(origin,'sobel'));
cs

 

3. 케니 엣지(Matlab 라이브러리)

 

1
figure, imshow(edge(origin,'canny'));
cs

 

결과

 

1. 결과 이미지 비교

  • Sobel mask

  • Canny edge

 

2. 시간 비교

  • MYsobel

  • LIBsobel

 

'영상처리 실습' 카테고리의 다른 글

[Opencv]여러가지 프로세싱 알고리즘 구현  (0) 2018.12.11
matlab wavelets toolbox  (0) 2018.12.06

+ Recent posts