วิธีค้นหาประเภทของวัตถุ Mat ที่มี Mat :: type () ใน OpenCV


118

ฉันสับสนกับtype()วิธีการของMatวัตถุใน OpenCV
หากฉันมีบรรทัดต่อไปนี้:

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

และtype = 16. ฉันจะทราบได้อย่างไรว่าเมทริกซ์คืออะไร?.
ฉันพยายามหาคำตอบในคู่มือหรือหนังสือสองสามเล่มโดยเปล่าประโยชน์


6
สำหรับการตีความโดยมนุษย์ชอบการใช้depth()และchannels()แทนที่จะใช้type()ซึ่งส่งกลับการผสมผสานที่ซับซ้อนระหว่างประเภทข้อมูลและจำนวนช่องสัญญาณ
BConic

@ แอลดูร์ค่าส่งคืนของความลึก () ยังไม่สามารถอ่านได้ คุณต้องเปรียบเทียบกับนิยาม: CV_8U, CV_8S ฯลฯ ...
Octopus

1
@octopus แน่ใจ แต่มีบิตของการปฏิบัติคุณสามารถเรียนรู้ร่วมกันรหัสซึ่งอยู่ไกลยากสำหรับdepth() type()
BConic

โปรดทราบว่าความลึก () ส่งกลับค่า CV enum สำหรับประเภทนี้ (ทำให้ผู้เริ่มต้นเข้าใจผิดเล็กน้อย) หากคุณต้องการขนาดของตัวเลขหนึ่งที่เก็บไว้ใน 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คุณสามารถเรียกได้ดังนี้:

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

จะส่งออกข้อมูลเช่น:

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

เป็นที่น่าสังเกตว่ายังมีวิธีเมทริกซ์Mat::depth()และMat::channels(). ฟังก์ชั่นนี้เป็นเพียงวิธีที่สะดวกในการรับการตีความที่มนุษย์สามารถอ่านได้จากการรวมกันของค่าทั้งสองซึ่งบิตทั้งหมดจะถูกเก็บไว้ในค่าเดียวกัน


7
ขอบคุณสำหรับฟังก์ชั่นนี้คุณทำให้ชีวิตฉันง่ายขึ้นมาก! น่าผิดหวังที่ฟังก์ชั่นดังกล่าวไม่ได้รวมอยู่ใน opencv thow
Milania

1
ฉันได้สร้าง Gist ด้วยวิธีการจากคำตอบใน Objective-C สนุก!
Tomasz Bąk

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

152

สำหรับวัตถุประสงค์ในการดีบักในกรณีที่คุณต้องการค้นหา Raw Mat :: ให้พิมพ์ดีบักเกอร์:

+--------+----+----+----+----+------+------+------+------+
|        | 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
ไม่มีความแตกต่างกัน
Kevin Johnsrude

1
ขอบคุณ นี่ควรเป็นคำตอบอันดับต้น ๆ
regomodo

32

ในส่วนหัว OpenCV " types_c.h " มีชุดของการกำหนดที่สร้างสิ่งเหล่านี้รูปแบบคือCV_bits{U|S|F}C<number_of_channels>
ตัวอย่างเช่นCV_8UC3หมายถึงตัวอักษรที่ไม่ได้ลงชื่อ 8 บิตช่อง 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 โดยตรงบนไดรฟ์ C ในโฟลเดอร์ opencv_2.4.11 ไฟล์ส่วนหัวจะอยู่ที่ C: \ opencv_2.4.11 \ build \ include \ opencv2 \ core \ types_c .h
user3731622

นอกจากนี้ถ้าคุณกำลังใช้ IDE ซึ่งรวมถึง "ไปทำคำนิยาม" การทำงานเช่น Visual Studio คุณสามารถพิมพ์cv::CV_8UคลิกขวาและเลือกGo to Definitionที่จะเปิดไฟล์ที่ถูกกำหนดไว้ซึ่งเป็นcv::CV_8U types_c.h
user3731622


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.