[opencv] Mat_ 클래스와 InputArray, OutputArray
정말 간만에 하는 것 같다. 얼른 기본클래스를 끝내고, 실질적인 영상처리에 돌입해야함.
텐서플로우도 조금씩 시작하고있고 처리할게 한 두개 밀려있다보니 계속 opencv를 미루다 하는 중..
나의 나중기억은 항상 보장할 수 없으므로 코드와 주석을 통한 로그를 남기도록 한다.
#pragma warning(disable: 4819)
#include "opencv.hpp"
#include <iomanip>
using namespace cv;
using namespace std;
void toThreshold(InputArray _src, OutputArray _dst, uchar threshVal);
int main()
{
Mat dstImage(2, 3, CV_32F);
for (int i = 0; i < dstImage.rows; i++) {
for (int j = 0; j < dstImage.cols; j++) {
dstImage.at<float>(i, j) = (float)(i* dstImage.cols + j);
}
}
Mat_<double> B = (Mat_<double>)dstImage;
//Mat_<float> B = (Mat_<float>)dstImage;
Mat_<float>& C = (Mat_<float>&)dstImage;
B(0, 0) = 10.0f; // C가 dstImage의 레퍼런스를 참고하기때문에 B에 변형을 가해서 확인.
// 하지만 dstImage와 B, C 모두 float으로 자료형이 설정돼있고, 타입캐스팅의 템플릿 역시 float이므로 동일한 메모리를 참고한다.
// B에서 Mat_<float> B 대신 Mat_<double> B를 하면 템플릿의 자료형 이 달라지므로 새로운 메모리를 할당하도록 한다.
cout << dstImage << endl;
cout << "------------------------" << endl;
cout << B << endl;
cout << "------------------------" << endl;
cout << C << endl;
cout << "------------------------" << endl;
//imshow("dstImage", dstImage);
//waitKey();
system("cls");
Mat_<Vec3b> image(400, 400, Vec3b(255, 255, 255));
for (int i = 0; i < 400; i++) {
image(i, i) = Vec3b(0, 0, 0); // 흰바탕에 검은 대각선 예상합니다.
}
for (int i = 0; i < 400; i++) {
for (int j = 0; j < 400; j++) {
image(i, j)[0] = 0; // 3채널이기 때문에.
image(i, j)[1] = 60;
image(i, j)[2] = 180; // 모든 채널을 건드려서 대각선도 덮어버림.
}
}
//imshow("image", image);
//waitKey(0);
system("cls");
Mat_<uchar> srcImage = imread("lena.jpg", IMREAD_GRAYSCALE);
float sum = 0;
for (int i = 0; i < srcImage.rows; i++) {
for (int j = 0; j < srcImage.cols; j++) {
sum += srcImage(i, j);
}
}
// Mat::total() : Returns the total number of array elements.
// 총 byte(uchar)를 더한 값을 225*225(가로 세로)로 나누면 평균 값이 나옴.
imshow("test", srcImage);
cout << sum << endl << srcImage.total() << endl;
cout << "Avg = sum / total = " << sum / srcImage.total() << endl;
cout << srcImage.dims << endl;
system("cls");
Mat_<float> AA(10, 10);
for (int i = 0; i < AA.rows; i++) {
for (int j = 0; j < AA.cols; j++) {
AA(i, j) = (float)(i*AA.cols + j);
}
}
cout << AA << endl;
cout << "sum(A) = " << cv::sum(AA) << endl;
float sum2 = 0;
Mat_<float>::iterator it = AA.begin(); // AA의 첫 포지션을 이터레이터로 지정
for (; it != AA.end(); it++) { // 횟수 제한없이 이터레이터가 AA의 끝을 만날 때까지 실행. it++는 일반적인 it.next()와 동일.
sum2 += *it; // 이터레이터가 가르키는 주소의 값은 float
}
cout << setw(10) << sum2 << endl;
Mat_<float> BB(10, 10);
Mat_<float>::const_iterator itAA = AA.begin();
Mat_<float>::iterator itBB = BB.begin();
for (; itAA != AA.end(); itAA++, itBB++) {
*itBB = *itAA;
}
cout << BB << endl;
// const한 iterator를 통해 BB로 AA값을 복사.
// InputArray, OutputArray
/*
InputArray는 벡터나 행렬을 인수로 전달할때 유용. R/O로 Mat을 인수로 전달하는 대신 InputArray로 인수를 전달
OutputArray는 벡터나 행렬을 출력으로 사용할 인수를 전달할 때 사용됌. R/W가능.
그렇다면 굳이 InputOutputArray가 존재하는 이유는?....
일단 InputArray < OutputArray < InputOutputArray 순으로 상속임.
*/
Mat srcImage2 = imread("lena.jpg", IMREAD_GRAYSCALE);
if (srcImage2.empty()) {
return -1;
}
Mat dstImage2;
float threshRatio = 0.8; // 값이 1에 가까울수록 밝은 픽셀만 0처리, 나머지는 255처리라 점점 어두워짐
if (threshRatio > 1.0 || threshRatio < 0.0) { // 올바르지않은 스레숄드 비율값이 들어왔을 때
return -1;
}
int ratioToVal = UCHAR_MAX * threshRatio;
toThreshold(srcImage2, dstImage2, ratioToVal);
imshow("test", dstImage2);
waitKey(0);
system("cls");
return 0;
}
void toThreshold(InputArray _src, OutputArray _dst, uchar threshVal) {
Mat src = _src.getMat(); // InputArray로 받아온 입력값은 getMat으로 Mat 객체를 받아올 수 있음
_dst.create(src.size(), src.type());
Mat dst = _dst.getMat();
for (int i = 0; i < src.rows; i++) {
for (int j = 0; j < src.cols; j++) {
if (src.at<uchar>(i, j) < threshVal) {
dst.at<uchar>(i, j) = 0;
}
else {
dst.at<uchar>(i, j) = 255;
}
}
}
}
카테고리: 개발노트
2개의 댓글
구농공 · 2019-03-01 10:48:22
앗! 제가 아는 묘아님이 맞으시려나…
예전 리에님블로그에서…
myoatm · 2019-03-01 15:13:56
안녕하세요, 반갑습니다!
개인서버로 이사하여 이쪽에만 일지를 남기고 있습니다.