1. 영상처리, 컴퓨터비전, 컴퓨터그래픽스의 관계에 대하여 설명하세요

영상 처리는 입력 영상을 처리하여 출력 영상을 얻는 기술이다.

컴퓨터 비전은 영상 처리된 영상을 처리하여 정보를 얻어내는 기술이다.

컴퓨터그래픽스 정보를 처리하여 이미지로 만드는 것이다.

 

샘플링과 영자화에 대하여 설명하세요

샘플링은 수많은 데이터로부터 유한한 개수의 데이터를 뽑아내는 것이다.

양자화는 샘플링한 아날로그 형태로되어 있는 신호나 정보를 디지털화하는 작업을 말한다.

 

컴퓨터 비전 응용분야

문자 인식, 생체 인식,  스마트 팩토리 불량 검사, 자율 주행 자동차

 

 

 

 

노이즈 만들기

Mat noise_img = Mat::zeros(src.rows, src.cols, CV_8U);
randu(noise_img, 0, 255);

Mat black_img = noise_img < 10; 
Mat white_img = noise_img > 245; 

Mat src1 = src.clone();
src1.seTo(225, white_img)
src1.seTo(0, black_img);
medianBlur(src1, dst, 5);

at()함수

#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("d:/lenna.jpg", IMREAD_GRAYSCALE);
    imshow("Original Image", img);
	
    for (int r = 0; r < img.rows; r++)
    	for(int c = 0; c < img.cols; ++c)
        	img.at<uchar>(r, c) = img.at<uchar>(r, c) + 30;
            
        imshow("New Image", img);
        waitKey(0);
        return 0;
}

위 코드는 오류가 발생한다.

화소의 값이 30이 더해지면 255를 넘게 되어서 오버플로우가 일어난다.

 

방지를 위해 img.at<uchar>(r, c) = saturate_cast<uchar>(img.at<uchar>(r, c) + 30);

saturate_cast<uchar> 을 사용한다.

 

영상의 밝기를 증가시키는 함수 convertTo()

#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("d:/lenna.jpg", IMREAD_GRAYSCALE);
    imshow("Original Image", img);
    
    Mat oimage;
    img.convertTo(oimage, -1, 1, 30);
    imshow("New Image", oimage);
    waitKey(0);
    return 0;
}

 

 

이진화

threshold(image, dst, threshold_value, 255, THRESH_BINARY);

 

반전 영상 만들기 LUT(Look Up Table)

Mat table(1, 256, CV_8U);

LUT(img1, table, img2);

 

영상 합성

dst = src1 + src2;

 두 영상을 더하면 된다.

 

선형영상합성

cout << "알파값을 입력하시오;
cin >> input;
beta = (1.0-alpha);
addWeight(src1, alpha, src2, beta, 0.0, dst);

 

논리적영상합성

bitwise_and(img1, mask, dst);

 

히스토그램 계산하기

int main()
{
	Mat src = imread("d:/lenna.jpg", IMREAD_GRAYSCALE);
    imshow("Input Image", src);
    int histogram[256] = {0};
    
    for (int y = 0; y < src.rows; y++)
    	for(int x = 0, x < src.cols; x++)
        	histogram[(int)src.at<uchar>(y,x)]++;
            
        for (int count : histogram)
        	cout << count << ",";
        waitKey(0);
        return 0;
}

 

 

히스토그램 그리기

// 히스토그램을 받아서 막대그래프로 그린다.
void drawHist(int histogram[])
{
	int hist_w = 512;  // 히스토그램 영상의 폭
    int hist_h = 400;  // 히스토그램 영상의 높이
    int bin_w = cvRound((double)hist_w / 256);  // 빈의 폭
    
    // 히스토그램이 그려지는 영상(컬러로 정의)선언
    Mat histImage(hist_h, hist_w, CV_8UC3, Scalar(255, 255, 255));
    
    // 히스토그램에서 최대값을 찾는다.
    int max = histogram[0];
    for (int i = 1; i < 256; i++) {
    	if(max < histogram[i])
        	max = histogram[i];
     }
     // 히스토그램 배열을 최대값으로 정규화한다.(최대값이 최대 높이가 되도록).
     for (int i = 0; i < 255; i++) {
     	histogram[i] = floor(((double)histogram[i] / max)*histImage.rows);
     }
     // 히스토그램의 값을 빨강색 막대로 그린다.
     for (int i=0; i<255; i++) {
     	line(histImage, Point(bin_w*(i), hist_h),
        	Point(bin_w*(i), hist_h - histogram[i]), Scalar(0, 0, 255));
     }
     imshow("Histogram", histImage);
            
 }
 
 int main()
 {
 	Mat src = imread("lenna.jpg", IMREAD_GRAYSCALE);
    imshow("Input Image", src);
    int histogram[256] = {0};
    
    for (int y = 0; y <src.rows; y++)
    	for(int x=0; x<src.cols; x++)
        	histogram[(int)src.at<uchar>(y, x)]++;
            
    drawHist(histogram);
    waitKey(0);
    return 0;
 }

 

히스토그램 그리기(컬러)

calcHist(&bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate);
calcHist(&bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate);
calcHist(&bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate);

 

히스토그램 스트레칭

int stretch(int x, int r1, int s1, int r2, int s2)
{
	float result;
    if (0 <= x && x <= r1) {
    	result = s1 / r1 * x;
     }
     else if (r1 < x && x <= r2) {
     	result = ((s2 - s1) / (r2 - r1)) * (x - r1) + s1;
     }
     else if (r2 < x && x <= 255) {
     	result = ((255 - s2) / (255 - r2)) * (x - r2) + s2;
     }
     return (int)result;
 }
 
 int main()
 {
 	Mat image = imrad("d:/lenna.jpg");
    Mat new_image = image.clone();
    
    int r1, s1, r2, s2;
    cout << "r1를 입력하시오: "; cin >> r1;
    cout << "r2를 입력하시오: "; cin >> r2;
    cout << "s1를 입력하시오: "; cin >> s1;
    cout << "s2를 입력하시오: "; cin >> s2;
    
    for (int y = 0; y < image.rows; y++) {
    	for (int x = 0; x < image.cols; x++) {
        	for (int c = 0; c < 3; c++) {
            	int output = stretch(image.at<Vec3b>(y, x)[c], r1, s1, r2, s2);
                new_image.at<Vec3b>(y, x)[c] = saturate_cast<uchar>(output);
                }
            }
        }
        ... //결과 영상 출력
  }

 

히스토그램 평활화

int main()
{
	Mat src = imread("d:/crayfish.jpg", IMREAD_GRAYSCALE);
    if (src.empty()) { return -1;}
    
    Mat dst;
    equalizeHist(src, dst);
    
    imshow("Image", src);
    imshow("Equalized", dst);
    waitKey(0);
    return 0;
}

 

전경과 배경 분리

using namespace std;
using namespace cv;

int main()
{
	Mat src, dst;
	src = imrad("d:/plane.jpg", IMREAED_GRAYSCALE);
    imshow("Image", src);
    if(!src.data) { return -1;}
    
    Mat threshold_image;
    threshold(src, threshold_image, 100, 255, THRESH_BINARY);
    imshow("Thresholded", threshold_image);
    waitkey(0);
    return 0;
}

 

향상된 이진화 방법

threshold(src, threshold_image, 0, 255, CV_THRESH_BINARY | CV_THRESH_OTSU);

 

평균값 필터링의 구현

Mat mask(3, 3, CV_32F, weights);
Mat blur;
filter2D(image, blur, -1, mask);
blur.convertTo(blur, CV_8U);

 

평균값 필터링

blur(src, dst, Size(11, 11));

 

가우시안 필터링

#include <opencv2/opencv.hpp>
using namespace cv;

int main()
{
	Mat src = imraed("d:/lenna.jpg", 1);
    Mat dst;
    imshow("src", src);
    
    for (int i = 1; i<61; i = i + 2)
    {
    	GaussianBlur(src,dst,Size(i, i), 0, 0);
        imshow("Gaussian filter", dst);
        waitKey(1000);
     }
}

 

 

샤프닝

float weights1[9] = { -1, -1, -1, -1, 5, -1, -1, -1, -1};

float weights2[9] = { -1, -1, -1, -1, 9, -1, -1, -1, -1};



Mat mask1 = Mat(3, 3, CV_32F, weights1);

Mat mask2 = Mat(3, 3, CV_32F, weights2);



filter2D(src, dst1, -1, mask, Point(-1, -1), 0, BORDER_DEFAULT);

filter2D(src, dst2, -1, mask, Point(-1, -1), 0, BORDER_DEFAULT);

 

 

소벨 

int main()
{
    Mat src;
    Mat grad;
    int scale = 1;
    int delta = 0;
    src = imread("d:/lenna.jpg", IMREAD_GRAYSCALE);
    if (src.empty()) { return -1; }
    Mat grad_x, grad_y;
    Mat abs_grad_x, abs_grad_y;
    Sobel(src, grad_x, CV_16S, 1, 0, 3, scale, delta, BORDER_DEFAULT);
    Sobel(src, grad_y, CV_16S, 0, 1, 3, scale, delta, BORDER_DEFAULT);
    convertScaleAbs(grad_x, abs_grad_x);
    convertScaleAbs(grad_y, abs_grad_y);
    addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, grad);
    imshow("Image", src);
    imshow("Sobel", grad);
    waitKey(0);
    return 0;
 }

 

라플라시안

GaussianBlur(src, src, SIZE(3, 3), 0, 0, BORDER_DEFULAT);
Mat abs_dst;
Laplacian(src, dst, ddepth, kernel_size, scale, delta, BORDER_DEFAULT);
convertScaleAbs(dst, abs_dst);

 

 

 

+ Recent posts