Lab.2 Point Processing and Histogram
I/O and Mat
- Mat 클래스 : OpenCV에서 이미지와 이미지의 정보 (사이즈 등)를 담게 되는 클래스
- 입출력 함수 : 기본적으로 Mat 객체로 반환하거나 Mat 객체를 입력으로 받아 수행
imread()
: 이미지 읽기
imshow()
: 이미지 출력
imwrite()
: 이미지 쓰기
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main() {
// 경로와 확장자에 주의!
Mat src_img = imread("images/landing.jpg", 1);
// flag = 1: 컬러 영상으로 읽음
// flag = 0 : 흑백 영상으로 읽음
// flage = -1 : 원본 영상의 형식대로 읽음
imshow("Test window", src_img);
waitKey(0);
destroyWindow("Test window");
}
imread()
: 이미지 읽기
imshow()
: 이미지 출력
imwrite()
: 이미지 쓰기
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
int main() {
// 경로와 확장자에 주의!
Mat src_img = imread("images/landing.jpg", 1);
// flag = 1: 컬러 영상으로 읽음
// flag = 0 : 흑백 영상으로 읽음
// flage = -1 : 원본 영상의 형식대로 읽음
imshow("Test window", src_img);
waitKey(0);
destroyWindow("Test window");
}
#include "opencv2/opencv.hpp"
를 이용하여 모든 헤더파일을 불러올 수 있지만, 그렇게 하면 프로그램 실행 속도가 느려지므로 필요한 헤더파일만 불러오도록 하자.
Pixel Value
- 이미지의 각 픽셀을 개별적으로 접근
- OpenCV의 함수들을 사용하게 되면 사용할 경우가 없으나, 픽셀 값을 각각 읽어 원하는 기능을 구현하거나 분석할 때 반드시 피룡함
- OpenCV의 컬러 mat는
BGR
채널 순서를 가지고 있음에 유의
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
Mat SpreadSalts(Mat img, int num) {
// num : 점을 찍을 개수
for (int n = 0; n < num; n++) {
int x = rand() % img.cols; // img.cols는 이미지의 폭 정보를 저장
int y = rand() % img.rows; // img.rows는 이미지의 높이 정보를 저장
/*
* 나머지는 나누는 수를 넘을 수 없으므로
* 이미지의 크기를 벗어나지 않도록 제한하는 역할을 해줌
*/
if (img.channels() == 1) {
// img.channels() : 이미지의 채널 수르 반환
img.at<char>(y, x) = 255; // 단일 채널 접근
}
else {
img.at<Vec3b>(y, x)[0] = 255; // Blue 채널 접근
img.at<Vec3b>(y, x)[1] = 255; // Green 채널 접근
img.at<Vec3b>(y, x)[2] = 255; // Rud 채널 접근
}
}
return img;
}
int main() {
Mat src_img = imread("images/landing.jpg", 0);
Mat salted_img = SpreadSalts(src_img, 1000);
imshow("Test window", salted_img);
waitKey(0);
destroyWindow("Test window");
}
- 강의 노트에는 함수의 반환형이
void
이나, 이를 salted_img라는 변수로 저장하기 위해 Mat
타입으로 반환하도록 변경
- 단일 채널은 그레이 스케일 이미지이다.
img.at(int x, int y)
: 각 원소에 접근하기 위해 사용
- uchar : 그레이(흑백) 이미지에 사용
- vec3b : 컬러 이미지에 사용, 3개의 unsigned char를 가지는 벡터
BGR
채널 순서를 가지고 있음에 유의#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
Mat SpreadSalts(Mat img, int num) {
// num : 점을 찍을 개수
for (int n = 0; n < num; n++) {
int x = rand() % img.cols; // img.cols는 이미지의 폭 정보를 저장
int y = rand() % img.rows; // img.rows는 이미지의 높이 정보를 저장
/*
* 나머지는 나누는 수를 넘을 수 없으므로
* 이미지의 크기를 벗어나지 않도록 제한하는 역할을 해줌
*/
if (img.channels() == 1) {
// img.channels() : 이미지의 채널 수르 반환
img.at<char>(y, x) = 255; // 단일 채널 접근
}
else {
img.at<Vec3b>(y, x)[0] = 255; // Blue 채널 접근
img.at<Vec3b>(y, x)[1] = 255; // Green 채널 접근
img.at<Vec3b>(y, x)[2] = 255; // Rud 채널 접근
}
}
return img;
}
int main() {
Mat src_img = imread("images/landing.jpg", 0);
Mat salted_img = SpreadSalts(src_img, 1000);
imshow("Test window", salted_img);
waitKey(0);
destroyWindow("Test window");
}
void
이나, 이를 salted_img라는 변수로 저장하기 위해 Mat
타입으로 반환하도록 변경img.at(int x, int y)
: 각 원소에 접근하기 위해 사용- uchar : 그레이(흑백) 이미지에 사용
- vec3b : 컬러 이미지에 사용, 3개의 unsigned char를 가지는 벡터
Histogram
: 픽셀 값의 분포를 나타낸 그래프
- 가능한 모든 픽셀 레벨에 대한 카운트로 구할 수 있음
- 이미지의 픽셀 값에 대한 경향성을 알 수 있으므로, 시각적인 분석/판단에 용이
// 히스토그램 계산 함수
void cv::calcHist( const Mat* images, // 입력 영상의 주소(& 붙여야 함)
int nimages, // 입력 영상의 개수
const int* channels, // 히스토그램을 구할 채널을 나타내는 배열
InputArray mask, // 계산을 수행할 범위 마스크, Mat()으로 전체 선택
OutputArray hist, // 히스토그램이 저장될 Mat
int dims,
const int* histSize, // 가능한 모든 픽셀 레벨 (일반 8bit 영상은 255)
const float ** ranges, // 히스토그램 범위
bool uniform = true, // 히스토그램이 등간격인지 아닌지
bool accumulate = false // 일반 히스토그램인지 누적 히스토그램인지
)
이를 사용해서 히스토그램을 출력하는 코드를 작성해보자.
#include <iostream>
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
using namespace std;
Mat getHistogram(Mat& src) {
Mat histogram;
const int* channel_numbers = { 0 };
float channel_range[] = { 0.0, 255.0 };
const float* channel_ranges = channel_range;
int number_bins = 255;
// 히스토그램 계산
calcHist(&src, 1, channel_numbers, Mat(), histogram, 1, &number_bins, &channel_ranges);
// 히스토그램 plot
int hist_w = 512;
int hist_h = 400;
int bin_w = cvRound((double)hist_w / number_bins);
Mat histImage(hist_h, hist_w, CV_8UC1, Scalar(0, 0, 0));
// 정규화
normalize(histogram, histogram, 0, histImage.rows, NORM_MINMAX, -1, Mat());
for (int i = 1; i < number_bins; i++) {
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(histogram.at<float>(i - 1))),
Point(bin_w * (i), hist_h - cvRound(histogram.at<float>(i))), Scalar(255, 0, 0), 2, 8, 0);
}
return histImage;
}
int main() {
Mat src_img = imread("images/landing.jpg", 0);
Mat hist_img = getHistogram(src_img);
imshow("Test window", hist_img);
waitKey(0);
destroyWindow("Test window");
}
Operations
- 산술 연산으로 두 영상을 합성하거나 영상의 값을 전체적으로 조절할 수 있음
- 산술 연산을 위한 함수가 따로 존재하지만, 산술 연산자도 사용 가능
virtual void cv::resize ( InputArray src,
OutputArray dst,
Size dsize,
double fx = 0,
double fy = 0,
int interpolation = INTER_LINEAR
)
virtual void cv::MatOp::add ( const MatExpr& expr1,
const MatExpr& expr2,
MatExpr& res
) const
virtual void cv::MatOp::add ( const MatExpr& expr1,
const Scalar& s,
MatExpr& res
) const
virtual void cv::MatOp::subtract ( const MatExpr& expr1,
const MatExpr& expr2,
MatExpr& res
) const
virtual void cv::MatOp::subtract ( const Scalar& s,
const MatExpr& expr,
MatExpr& res
) const
virtual void cv::resize ( InputArray src,
OutputArray dst,
Size dsize,
double fx = 0,
double fy = 0,
int interpolation = INTER_LINEAR
)
virtual void cv::MatOp::add ( const MatExpr& expr1,
const MatExpr& expr2,
MatExpr& res
) const
virtual void cv::MatOp::add ( const MatExpr& expr1,
const Scalar& s,
MatExpr& res
) const
virtual void cv::MatOp::subtract ( const MatExpr& expr1,
const MatExpr& expr2,
MatExpr& res
) const
virtual void cv::MatOp::subtract ( const Scalar& s,
const MatExpr& expr,
MatExpr& res
) const
Logical Operations
-
영상에 대한 논리적 연산으로 두 영상을 합성하거나 Masking할 수 있음
void cv::bitwise_and( inputArray src1,
inputArray src2,
OutputArray dst,
inputArray mask = noArray()
)
void cv::bitwise_or( inputArray src1,
inputArray src2,
OutputArray dst,
inputArray mask = noArray()
)
void cv::bitwise_not( inputArray src1,
inputArray src2,
OutputArray dst,
inputArray mask = noArray()
)
<p align="center" style="color:gray">
Binarization
- 영상을 두 개의 값으로 표현하는 것 (0 or 1, 0 or 255)
- Grayscale 영상에서 임계점보다 크고 작음을 기준으로 영상을 두 개의 값으로 나눌 수 있음
- 적절한 임계 값을 설정하면 영상 속에서 유용한 마스크를 획득할 수 있음
- 적절한 임계 값은 히스토그램을 참조해 선택하거나 자동으로 찾아주는 알고리즘을 이용해 탐색 (OTSU)
Mat color_img = imread("mark.jpg", 1);
Mat gray_img;
// 이진화를 위해 color에서 grayscale 영상으로 변환
cvtColor(color_img, gray_img, CV_BGR2GRAY);
Mat binary_img1, binary_img2;
// 임계값 지정 이진화
threshold(gray_img, binary_img1, 127, 255, THRESH_BINARY);
// 임계값 자동 이진화
threshold(gray_img, binary_img1, 0, 255, THRESH_OTSU);
영상에 대한 논리적 연산으로 두 영상을 합성하거나 Masking할 수 있음
void cv::bitwise_and( inputArray src1,
inputArray src2,
OutputArray dst,
inputArray mask = noArray()
)
void cv::bitwise_or( inputArray src1,
inputArray src2,
OutputArray dst,
inputArray mask = noArray()
)
void cv::bitwise_not( inputArray src1,
inputArray src2,
OutputArray dst,
inputArray mask = noArray()
)
<p align="center" style="color:gray">
- 영상을 두 개의 값으로 표현하는 것 (0 or 1, 0 or 255)
- Grayscale 영상에서 임계점보다 크고 작음을 기준으로 영상을 두 개의 값으로 나눌 수 있음
- 적절한 임계 값을 설정하면 영상 속에서 유용한 마스크를 획득할 수 있음
- 적절한 임계 값은 히스토그램을 참조해 선택하거나 자동으로 찾아주는 알고리즘을 이용해 탐색 (OTSU)
Mat color_img = imread("mark.jpg", 1);
Mat gray_img;
// 이진화를 위해 color에서 grayscale 영상으로 변환
cvtColor(color_img, gray_img, CV_BGR2GRAY);
Mat binary_img1, binary_img2;
// 임계값 지정 이진화
threshold(gray_img, binary_img1, 127, 255, THRESH_BINARY);
// 임계값 자동 이진화
threshold(gray_img, binary_img1, 0, 255, THRESH_OTSU);
Author And Source
이 문제에 관하여(Lab.2 Point Processing and Histogram), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@leeeeeyeon/Lab.2-Point-Processing-and-Histogram-4io4rr2m저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)