OpenCV에서 Mat :: type ()을 사용하여 Mat 객체의 유형을 찾는 방법


118

OpenCV type()Mat객체 방법 과 혼동됩니다 .
다음 줄이있는 경우 :

mat = imread("C:\someimage.jpg");
type = mat.type();

type = 16. 매트 매트릭스의 유형을 어떻게 알 수 있습니까?.
나는 그 매뉴얼이나 책 몇 권에서 답을 헛되이 찾으려고 노력했다.


6
인간의 해석의 사용을 선호 depth()하고 channels()사용하는 대신, type()데이터 유형 및 채널 수 사이의 복잡한 혼합을 반환한다.
BConic

@Aldur, depth ()의 반환 값은 여전히 ​​사람이 읽을 수 없습니다. 정의와 비교해야합니다 : CV_8U, CV_8S 등 ...
Octopus

1
@octopus는 확실하지만 약간의 연습을 통해 일반적인 depth()코드를 배울 수 있습니다 type().
BConic

depth ()는이 유형에 대한 CV 열거 형 값을 반환합니다 (초보자에게 약간 오해의 소지가 있음). Mat에 바이트 단위로 저장된 숫자 하나의 크기가 필요한 경우 Mat.elemSize1 ()을 사용하십시오. 예를 들어 다른 유형이 전달되는 함수 내에서 런타임시 유형이 필요한 경우 여기에서 템플릿 유형 TypeDepth <>를 찾을 수 있습니다 (CV 깊이가 아니므로 이름을 바꿔야합니다). stackoverflow.com/questions/ 15245262 /…
karsten

답변:


196

다음은 런타임에 opencv 행렬을 식별하는 데 도움이되는 편리한 함수입니다. 적어도 디버깅에 유용하다고 생각합니다.

string type2str(int type) {
  string r;

  uchar depth = type & CV_MAT_DEPTH_MASK;
  uchar chans = 1 + (type >> CV_CN_SHIFT);

  switch ( depth ) {
    case CV_8U:  r = "8U"; break;
    case CV_8S:  r = "8S"; break;
    case CV_16U: r = "16U"; break;
    case CV_16S: r = "16S"; break;
    case CV_32S: r = "32S"; break;
    case CV_32F: r = "32F"; break;
    case CV_64F: r = "64F"; break;
    default:     r = "User"; break;
  }

  r += "C";
  r += (chans+'0');

  return r;
}

M유형 Mat이 var 이면 다음과 같이 호출 할 수 있습니다.

string ty =  type2str( M.type() );
printf("Matrix: %s %dx%d \n", ty.c_str(), M.cols, M.rows );

다음과 같은 데이터를 출력합니다.

Matrix: 8UC3 640x480 
Matrix: 64FC1 3x2 

Matrix 메서드 Mat::depth()Mat::channels(). 이 함수는 비트가 모두 동일한 값에 저장된 두 값의 조합에서 사람이 읽을 수있는 해석을 얻는 편리한 방법입니다.


7
이 기능 덕분에 내 인생이 훨씬 쉬워졌습니다! 그러한 기능이 이미 opencv thow에 통합되어 있지 않다는 점에 실망했습니다.
Milania 2014 년

1
Objective-C의 답변에서 방법으로 Gist를 만들었습니다. 즐겨!
Tomasz Bąk 2014

1
유형에 대한 개요는이 답변 (5 = 32F, 6 = 64F)도 참조하십시오. stackoverflow.com/questions/12335663/…
Lenar Hoyt

누군가 실제로 이것을 openCV의 편리한 기능으로 만들 수 있습니까?
Sharan Duggirala

1
얻으려면 depth그리고 chans당신은 매크로를 사용할 수 CV_MAT_DEPTH(type)CV_MAT_CN(type)각각. 또한 유형은이어야하며 대신 int을 사용할 수 있습니다 . to_string(chans)chans+'0'
John

151

디버거에서 원시 Mat :: type을 조회하려는 경우 디버깅 목적으로 :

+--------+----+----+----+----+------+------+------+------+
|        | C1 | C2 | C3 | C4 | C(5) | C(6) | C(7) | C(8) |
+--------+----+----+----+----+------+------+------+------+
| CV_8U  |  0 |  8 | 16 | 24 |   32 |   40 |   48 |   56 |
| CV_8S  |  1 |  9 | 17 | 25 |   33 |   41 |   49 |   57 |
| CV_16U |  2 | 10 | 18 | 26 |   34 |   42 |   50 |   58 |
| CV_16S |  3 | 11 | 19 | 27 |   35 |   43 |   51 |   59 |
| CV_32S |  4 | 12 | 20 | 28 |   36 |   44 |   52 |   60 |
| CV_32F |  5 | 13 | 21 | 29 |   37 |   45 |   53 |   61 |
| CV_64F |  6 | 14 | 22 | 30 |   38 |   46 |   54 |   62 |
+--------+----+----+----+----+------+------+------+------+

예를 들어 type = 30이면 OpenCV 데이터 유형은 CV_64FC4입니다. type = 50이면 OpenCV 데이터 유형은 CV_16UC (7)입니다.


6
C (X)는 무엇을 의미합니까?
alanwsx

5
^ 행렬에서의 채널의 수
Arijit

3
^ 그러면 C5와 C (5)의 차이점은 무엇입니까?
Mateen Ulhaq

1
다른 점이 없다.
케빈 Johnsrude

1
감사. 이것이 최고의 답변이어야합니다
regomodo

32

OpenCV 헤더 " types_c.h "에는이를 생성하는 정의 세트가 있습니다. 형식은 CV_bits{U|S|F}C<number_of_channels>
예를 들어 CV_8UC38 비트 부호없는 문자, 3 개의 색상 채널을 의미합니다. 각 이름은 해당 파일의 매크로를 사용하여 임의의 정수에 매핑됩니다.

편집 : 예를 들어 " types_c.h "를 참조하십시오 .

#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))

eg.
depth = CV_8U = 0
cn = 3
CV_CN_SHIFT = 3

CV_MAT_DEPTH(0) = 0
(((cn)-1) << CV_CN_SHIFT) = (3-1) << 3 = 2<<3 = 16

따라서이 CV_8UC3 = 16 번호를 사용해서는 안됩니다 type() == CV_8UC3. 내부 OpenCV 배열이 어떤 유형인지 알아야하는지 확인하십시오 .
OpenCV는 jpeg를 BGR (또는 '0'을으로 전달하는 경우 회색조)로 변환 imread하므로 원본 파일에 대해 아무것도 알려주지 않습니다.


types_c.h코어 모듈에 있다는 것을 아는 것이 유용 합니다. 예를 들어 OpenCV가 opencv_2.4.11 폴더의 C 드라이브에 직접 설치된 경우 헤더 파일은 C : \ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c에 있습니다. .h
user3731622 '162017-08-29

당신이 포함하는 IDE를 사용하는 경우 또한, 당신은 입력 할 수 있습니다 비주얼 스튜디오와 같은 기능 "정의 할 가서" cv::CV_8U마우스 오른쪽 단추로 클릭하고 Go to Definition파일을 열 수 cv::CV_8U있는 정의를 types_c.h.
user3731622 17:53에


8

디버깅 목적으로 @Octopus의 답변에서 함수에 약간의 유용성을 추가했습니다.

void MatType( Mat inputMat )
{
    int inttype = inputMat.type();

    string r, a;
    uchar depth = inttype & CV_MAT_DEPTH_MASK;
    uchar chans = 1 + (inttype >> CV_CN_SHIFT);
    switch ( depth ) {
        case CV_8U:  r = "8U";   a = "Mat.at<uchar>(y,x)"; break;  
        case CV_8S:  r = "8S";   a = "Mat.at<schar>(y,x)"; break;  
        case CV_16U: r = "16U";  a = "Mat.at<ushort>(y,x)"; break; 
        case CV_16S: r = "16S";  a = "Mat.at<short>(y,x)"; break; 
        case CV_32S: r = "32S";  a = "Mat.at<int>(y,x)"; break; 
        case CV_32F: r = "32F";  a = "Mat.at<float>(y,x)"; break; 
        case CV_64F: r = "64F";  a = "Mat.at<double>(y,x)"; break; 
        default:     r = "User"; a = "Mat.at<UKNOWN>(y,x)"; break; 
    }   
    r += "C";
    r += (chans+'0');
    cout << "Mat is of type " << r << " and should be accessed with " << a << endl;

}

6

이것은 다른 몇 명의 답변을 받았지만 저에게 정말 잘 맞는 솔루션을 찾았습니다.

System.out.println(CvType.typeToString(yourMat));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.