[2023-04-20] 4. 영상의 산술 및 논리 연산
영상의 산술 및 논리 연산
덧셈 연산
- 두 영상의 같은 위치에 존재하는 픽셀 값을 더하여 결과 영상의 픽셀 값으로 설정
- 덧셈의 결과가 255보다 클 경우 픽셀 값을 255로 설정하는 포화 연산을 진행함
- 많은 결과 픽셀들이 두 픽셀의 합으로 인해 완전한 흰색인 255로 표현된 것을 확인할 수 있음
void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray(), int dtype = -1);
- src1 : 첫 번째 입력 행렬 또는 스칼라
- src2 : 두 번째 입력 행렬 또는 스칼라
- dst : 출력 행렬, dst의 깊이는 src1, src2의 깊이와 같거나 또는 dtype 인자에 의해 결정됨
- mask : 마스크 영상, mask 행렬 원소 값이 0이 아닌 위치에서만 연산을 수행함
- dtype : 출력 행렬의 깊이
가중치 합
- 두 영상의 같은 위치에 존재하는 픽셀 값에 대하여 가중합을 계산하여 결과 영상의 픽셀 값으로 설정
- 보통 알파와 베타의 합이 1이 되도록 설정함
- 알파와 베타의 합이 1일 경우에는 saturate안의 값이 0~255 사이의 값이 나오므로 포화 연산까지 안감
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);
- src1 : 첫 번째 입력 행렬
- alpha : src1 행렬의 가중치
- src2 : 두 번째 입력 행렬
- beta : src2 행렬의 가중치
- gamma : 가중합 결과에 추가적으로 더할 값
- dst : 출력 행렬, 입력 행렬과 같은 크기, 같은 채널 수
- dtype : 출력 행렬의 깊이
평균 연산
- 가중치 알파와 베타를 둘 다 0.5로 설정
평균 연산의 응용
- 잡음 제거
- 같은 장면을 여러분 촬영하면 같은 부분에 대하여 다른 값들이 들어가는 경우가 있는데 (어떤 값은 + a, 어떤 값은 -a) 이렇게 들어가는 잡음의 합은 전체적으로 평균이 0으로 동작함
- 같은 장면을 여러분 촬영해서 노이즈 없는 선명한 영상을 얻을 수 있음
- 아래 사진 같은 경우 건물 아래에 사람과 차들이 많이 돌아다니지만 사람과 차들이 움직이는 어떤 패턴이 긴 시간으로 보면 노이즈로 해당됨
- 위에 나와있는 건물은 전혀 움직이지 않으므로 건물만 촬영되고 사람과 차는 나타나지 않는 사진으로 결과를 도출할 수 있음
뺄셈 연산
- 두 영상의 같은 위치에 존재하는 픽셀 값에 대하여 뺄셈 연산을 수행하여 결과 영상의 픽셀 값으로 설정
- 뺄셈 결과가 0보다 작으면 픽셀 값을 0으로 설정하는 포화 연산을 진행함
- 덧셈 연산과 달리 뺄셈 연산은 영상의 순서에 따라 결과가 달라짐
void substract(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray(), int dtype =-1);
- src1 : 첫 번째 입력 행렬 또는 스칼라
- src2 : 두 번째 입력 행렬 또는 스칼라
- dst : 출력 행렬, dst의 깊이는 src1, src2의 깊이와 같거나 또는 dtype 인자에 의해 결정됨
- mask : 마스크 영상, mask 행렬 원소 값이 0이 아닌 위치에서만 연산을 수행함
- dtype : 출력 행렬의 깊이
차이 연산
- 두 입력 연산에 대하여 뺄셈 연산을 수행한 후, 그 절댓값을 이용하여 결과 영상을 생성하는 연산
- 뺄셈 연산과 달리 입력 영상 순서에 영향을 주지 않음
- 영상의 다른 부분(변화된 부분)을 찾기 위해 많이 사용됨
- 변화가 있는 부분에 대해서만 0보다 큰 값이 나타나고 나머진 0의 값으로 나타남
void absdiff(InputArray src1, InputArray src2, OutputArray dst);
- src1 : 첫 번째 입력 행렬 또는 스칼라
- src2 : 두 번째 입력 행렬 또는 스칼라
- dst : 출력 행렬(차영상), 입력 행렬과 같은 크기, 같은 채널 수
예제 코드
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat src1 = imread("lenna256.bmp", IMREAD_GRAYSCALE);
Mat src2 = imread("square.bmp", IMREAD_GRAYSCALE);
if (src1.empty() || src2.empty()) {
cerr << "Image load failed!" << endl;
return -1;
}
if (src1.size() != src2.size() || src1.type() != src2.type()) {
cerr << "The images are different in size or type!" << endl;
return -1;
}
imshow("src1", src1);
imshow("src2", src2);
Mat dst1, dst2, dst3, dst4;
add(src1, src2, dst1); // 덧셈 연산
addWeighted(src1, 0.5, src2, 0.5, 0, dst2); // 알파와 베타값이 0.5이므로 평균
subtract(src1, src2, dst3); // 뺄셈 연산
absdiff(src1, src2, dst4); // 차이 연산
imshow("dst1", dst1);
imshow("dst2", dst2);
imshow("dst3", dst3);
imshow("dst4", dst4);
waitKey();
}
- 실행결과
- src2의 검정색은 0이고 하얀색 부분이 255 이므로 src1 와 더하면 흰색은 무조건 255 이상의 값이 되므로 포화 연산 되고 검정색 부분은 0이므로 기존 src1과 같은 값이 나오게 됨
- dst2는 두 입력 연산의 평균 연산의 값
- dst3는 dsr1과 반대로 255를 뺏으니 0보다 작아져서 가운데가 검정색으로 되었고 테두리는 0으로 빼서 변화가 없음
- dst4는 기존 src1에서 흰색인 0을 빼도 같은 값이 나오지만 기존 src1에서 255의 값을 빼고 절댓값을 씌우면 그레이스케일 값이 반전되는 것을 확인
행렬의 논리 연산
void bitwise_and(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray());
void bitwise_or(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray());
void bitwise_xor(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray());
void bitwise_not(InputArray src, OutputArray dst, InputArray mask = noArray());
- src1 : 첫 번째 입력 행렬 또는 스칼라
-
src1 : 첫 번째 입력 행렬 또는 스칼라
- src : 입력 행렬 또는 스칼라
- dst : 출력 행렬, 입력 행렬과 같은 크기, 같은 채널 수
- mask : 마스크 행렬
예제 코드
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
int main()
{
Mat src1 = imread("lenna256.bmp", IMREAD_GRAYSCALE);
Mat src2 = imread("square.bmp", IMREAD_GRAYSCALE);
if (src1.empty() || src2.empty()) {
cerr << "Image load failed!" << endl;
return -1;
}
imshow("src1", src1);
imshow("src2", src2);
Mat dst1, dst2, dst3, dst4;
bitwise_and(src1, src2, dst1);
bitwise_or(src1, src2, dst2);
bitwise_xor(src1, src2, dst3);
bitwise_not(src1, dst4);
imshow("dst1", dst1);
imshow("dst2", dst2);
imshow("dst3", dst3);
imshow("dst4", dst4);
waitKey();
}
- 실행 결과
- src2의 검정색 부분은 0000000 으로 2진수로 표현이 가능하고
- src2의 흰색 부분은 11111111로 2진수로 표현이 가능함