샘플 Mat : 5000 x 3000 BGR Color All Black
cv::Mat image = cv::Mat::zeros(cv::Size(5000, 3000),CV_8UC3); |
RGB 의 합을 계산
방법 1) at<픽셀타입>(y좌표, x좌표)
int sum = 0; for (int i = 0; i < image.rows; i++) { for (int j = 0; j < image.cols; j++) { // gray 이미지의 경우 // uchar pixel = image.at<uchar>(i, j); cv::Vec3b pixel = image.at<cv::Vec3b>(i, j); sum += pixel[2] + pixel[1] + pixel[0]; } } |
방법 2) 선두 메모리 포인터 사용
int sum = 0; for (int i = 0; i < image.rows; i++) { // 로우의 선두 포인터 const cv::Vec3b* ptr = image.ptr<cv::Vec3b>(i); for (int j = 0; j < image.cols; j++) sum += ptr[j][2] + ptr[j][1] + ptr[j][0]; } |
방법 3) 넓이 메모리가 width와 같을 경우(넓이가 8의 배수)
int sum = 0; int width = image.cols; int height = image.rows; if (image.isContinuous()) { width *= height; height = 1; } for (int i = 0; i < height; i++) { const cv::Vec3b* ptr = image.ptr<cv::Vec3b>(i); for (int j = 0; j < width; j++) sum += ptr[j][2] + ptr[j][1] + ptr[j][0]; } |
방법 4) iterator 를 이용
int sum = 0; cv::MatConstIterator_< cv::Vec3b > it = image.begin<cv::Vec3b>(); cv::MatConstIterator_< cv::Vec3b > it_end = image.end<cv::Vec3b>(); for (; it != it_end; ++it) { cv::Vec3b pixel = ((cv::Vec3b)*it); sum += pixel[2] + pixel[1] + pixel[0]; } |
실행시간 비교 (본인 PC기준)
단위 : nanosec
1 sec=1 000 milisec=1 000 000 microsec=1 000 000 000 nanosec
방법 | 1차 | 2차 | 3차 |
1 | 100 | 0 | 0 |
2 | 100 | 0 | 0 |
3 | 0 | 0 | 100 |
4 | 10771700 | 9528100 | 9226600 |
결론
아주 빅 사이즈의 이미지라면 액세스의 방법에 따라 시간차가 나겠지만 왠만한 사이즈는 무시할 정도의 시간이다.
'opencv' 카테고리의 다른 글
C# 와 C++/CLI Dll 사이의 이미지 전달 (0) | 2025.02.10 |
---|---|
(opencv) 이미지위의 직선상의 픽셀위치 구하기 (0) | 2025.02.08 |
contour / labelling (0) | 2023.12.07 |
공백 메우기 (2) | 2023.12.02 |
b/w 이미지의 칼럼(수직방향)별 검정(=0)픽셀수 카운트 (0) | 2023.12.02 |