| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
- 스택
- 유도클래스
- 참조자
- 기본클래스
- 코딩테스트
- 백준
- 멤버함수로구현
- 상속
- 다형성
- C++
- OpenCV
- 얕은복사
- 동적바인딩
- 포인터
- 연산자오버로딩
- 11382번
- STL
- 인프런
- 코드잇
- list comprehension
- 제네릭프로그래밍
- 람다식
- c++코딩테스트합격자되기
- python
- 주피터
- 프로그래머스lv2
- OOP
- 깊은복사
- 데이터사이언스
- 점프투파이썬
- Today
- Total
WjExplor Story
01강 opencv 자료형 공부하기 본문
openCV 상수 명칭, 자료형
#include "opencv2/opencv.hpp"
using namespace cv;
using namespace std;
int main()
{
Mat M1(1, 2, CV_8S); // CV_8S CV_depth {U|S|F}C(#channel)
Mat M2(1, 2, CV_8UC3); // CV_8UC3
M1.at<char>(0, 0) = 1;
M1.at<char>(0, 1) = 2;
M2.at<Vec<uchar, 3>>(0, 0) = Vec3d(11, 12, 13);
M2.at<Vec<uchar, 3>>(0, 1) = Vec3d(10, 9, 8);
cout << "M1 = " << M1 << endl;
cout << "M1 depth = " << M1.depth() << endl;
cout << "M2 = " << M2 << endl;
cout << "M2 channels = " << M2.channels() << endl;
}
코드 설명
1. Mat 설정
CV_depth {U|S|F}
U : Unsigned
S : signed
F : Float
3가지를 지정합니다.
C(채널) 이 있다면 그 채널 갯수를 적어줄때 반드시 C라고 정의해야합니다.
Mat 자료형(행렬) 입니다.
이 행렬을 2개 선언하고 (1,2) 에서 각각 자료의 크기를 설정합니다.
CV_8UC3 은 채널이 3개이며 CV_8S 는 채널 갯수를 기입하지 않아서 채널이 1개입니다.
흑백(모노) 인 경우 채널이 1개 입니다.
컬러는 RGB 3가지 색상을 가지고 혼합하였습니다.
그래서 3채널을 쓰는것입니다.
CV_8S, CV_8UC3 등은 미리 정의된 상수형 변수입니다.DataType<char>::type 으로 정의할 수 있지만 간소하게 설정한것입니다.
2. M1 , M2 대입 값
M1.at<char>(0, 0) = 1;M2.at<char>(0, 1) = 2;
M1 이라는 행렬 중
(0,0) 캐릭터를 1로 대입(설정) 한 것입니다.
(0,1) 캐릭터를 2로 대입(설정)한 것입니다.
M2.at<Vec<uchar, 3>>(0, 0) = Vec3d(11, 12, 13);M2.at<Vec<uchar, 3>>(0, 1) = Vec3d(10, 9, 8);
M2 는 채널이 3개입니다 (CV_8UC3)
Vec 함수를 통해 가지고
(0,0) 에 있는 3가지의 값을 각각 정한 것 입니다. (11 , 12, 13)
(0,1) 도 마찬가지로 (10, 9, 8) 로 정하였습니다.
(GPT 에게 실무에 쓰는 코드 예제 물어봤습니다.)
Mat::at<T>()는 OpenCV에서 픽셀이나 행렬 원소에 직접 접근할 때 매우 흔하게 사용하는 함수
다만 실무에서는 상황에 따라 다음과 같이 구분해서 사용합니다.
| 방법 | 사용 빈도 | 특징 |
|---|---|---|
at<T>() |
높음 | 직관적, 안전성 좋음 |
ptr<T>() |
매우 높음 | 속도가 빠름 |
| 반복자(iterator) | 낮음 | STL 스타일 |
OpenCV 함수 사용 (threshold, cvtColor 등) |
매우 높음 | 실무에서 가장 많음 |
1. 현재 코드 설명
Mat M1(1, 2, CV_8S);
1행 2열의 signed char 행렬
[ ?, ? ]M1.at<char>(0,0) = 1;
M1.at<char>(0,1) = 2;
결과
[1, 2]Mat M2(1, 2, CV_8UC3);
1행 2열
채널 3개(B,G,R)
[(B,G,R), (B,G,R)]M2.at<Vec3b>(0,0) = Vec3b(11,12,13);
실제로는 이렇게 쓰는 것이 일반적입니다.
Vec3b
는
typedef Vec<uchar,3> Vec3b;
의 별칭입니다.
주의할 점
작성하신 코드
M2.at<Vec<uchar,3>>(0,0) = Vec3d(11,12,13);
은 타입이 다릅니다.
왼쪽
Vec<uchar,3>
오른쪽
Vec3d
(double)
실무에서는 보통
M2.at<Vec3b>(0,0) = Vec3b(11,12,13);
처럼 동일 타입을 사용합니다.
가장 흔한 예제 1 : 그레이스케일 픽셀 읽기
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("lenna.png", IMREAD_GRAYSCALE);
uchar pixel = img.at<uchar>(100, 200);
printf("%d\n", pixel);
}
좌표
(y=100, x=200)의 밝기값을 읽습니다.
가장 흔한 예제 2 : 밝기 증가
실무 교육에서 가장 먼저 만드는 예제입니다.
#include <opencv2/opencv.hpp>
using namespace cv;
int main()
{
Mat img = imread("lenna.png", IMREAD_GRAYSCALE);
for(int y=0; y<img.rows; y++)
{
for(int x=0; x<img.cols; x++)
{
uchar& pixel = img.at<uchar>(y, x);
pixel = saturate_cast<uchar>(pixel + 50);
}
}
imshow("result", img);
waitKey();
}
원본보다 50 밝아집니다.
가장 흔한 예제 3 : 컬러 영상 접근
Mat img = imread("lenna.png");
Vec3b color = img.at<Vec3b>(100, 200);
cout << "B = " << (int)color[0] << endl;
cout << "G = " << (int)color[1] << endl;
cout << "R = " << (int)color[2] << endl;
OpenCV는
RGB
가 아니라
BGR
순서입니다.
가장 흔한 예제 4 : 빨간색만 제거
컴퓨터비전 입문자가 많이 만드는 코드입니다.
Mat img = imread("lenna.png");
for(int y=0; y<img.rows; y++)
{
for(int x=0; x<img.cols; x++)
{
Vec3b& pixel = img.at<Vec3b>(y, x);
pixel[2] = 0;
}
}
imshow("result", img);
waitKey();
결과
R = 0이 되어 빨간 성분이 제거됩니다.
실무 스타일 예제 5 : 특정 밝기 이상 검출
비전 검사 장비에서 흔한 패턴입니다.
Mat src = imread("part.png", IMREAD_GRAYSCALE);
Mat dst(src.size(), CV_8UC1);
for(int y=0; y<src.rows; y++)
{
for(int x=0; x<src.cols; x++)
{
uchar pixel = src.at<uchar>(y,x);
if(pixel > 150)
dst.at<uchar>(y,x) = 255;
else
dst.at<uchar>(y,x) = 0;
}
}
이것이 Threshold 알고리즘의 가장 기본 형태입니다.
실제 현장에서는 다음 OpenCV 함수를 사용합니다.
threshold(src, dst, 150, 255, THRESH_BINARY);
실무 스타일 예제 6 : 불량 픽셀 개수 세기
공장 자동화 비전검사에서 자주 나오는 패턴입니다.
int count = 0;
for(int y=0; y<img.rows; y++)
{
for(int x=0; x<img.cols; x++)
{
if(img.at<uchar>(y,x) > 200)
count++;
}
}
cout << "Bright Pixel = "
<< count << endl;
응용 예
- 이물질 검사
- 스크래치 검사
- LED 점등 검사
- 인쇄 품질 검사
현업에서는 언제 at<T>()를 쓰나?
자주 사용
img.at<uchar>(y,x)
img.at<Vec3b>(y,x)
- 알고리즘 공부
- 프로토타입 제작
- 디버깅
- 픽셀 확인
대용량 영상 처리
실무에서는 더 빠른 방법 사용
uchar* row = img.ptr<uchar>(y);
row[x]
예
for(int y=0; y<img.rows; y++)
{
uchar* row = img.ptr<uchar>(y);
for(int x=0; x<img.cols; x++)
{
row[x] = 255 - row[x];
}
}
at<T>()보다 빠르기 때문에 검사 장비나 실시간 비전 시스템에서는 ptr<T>()를 자주 사용합니다.
컴퓨터비전 담당자가 실제로 자주 보는 코드
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
for(int y=0; y<gray.rows; y++)
{
for(int x=0; x<gray.cols; x++)
{
uchar pixel = gray.at<uchar>(y,x);
if(pixel > 120)
gray.at<uchar>(y,x) = 255;
else
gray.at<uchar>(y,x) = 0;
}
}
하지만 현업에서는 결국 아래 한 줄로 바뀝니다.
threshold(gray, gray, 120, 255, THRESH_BINARY);
즉,
at<T>()로 원리를 이해한다.- OpenCV 함수를 배운다.
- 속도가 중요하면
ptr<T>()를 사용한다.
이 순서로 학습하는 것이 일반적입니다.
추가로 Mat, Vec3b, Scalar, ptr<T>(), step, isContinuous()까지 이해하면 OpenCV C++ 실무 입문 수준을 넘어서게 됩니다.
'C++ > C++ : openCV' 카테고리의 다른 글
| 02-1강 Point2f 기본 사용법 정리: 좌표 연산, 내적(dot), 크기(norm), 외적(cross) (0) | 2026.06.15 |
|---|---|
| opencv (c++) 연동하기 (0) | 2026.06.14 |