[{"data":1,"prerenderedAt":9281},["ShallowReactive",2],{"wiki-page-/en-us/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun":3,"wiki-doc-items-/en-us/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun":9249,"language-switcher-data-/en-us/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun":9265,"wiki-i18n-paths-/en-us/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun":9280},{"id":4,"title":5,"body":6,"canonicalPath":9231,"chapter":871,"chapterSort":9232,"date":9233,"description":12,"docI18nKey":9234,"docKey":9235,"docRoot":9236,"docTitle":9237,"extension":9238,"i18nKey":9239,"isBlogPost":9240,"isWikiDoc":398,"isWikiIndex":9240,"layout":9241,"legacyPath":9241,"locale":9242,"localeSlug":9243,"meta":9244,"navigation":398,"path":9231,"seo":9245,"sourcePath":9246,"sourceStem":9239,"stem":9247,"wikiDepth":90,"__hash__":9248},"content/_i18n/en-us/wiki/2026-04-13-OpenCV教程/ch2-数据载入、显示与保存.md","Data loading, display, and saving",{"type":7,"value":8,"toc":9224},"minimark",[9,13,18,34,41,46,49,59,62,65,68,71,77,151,185,188,191,196,199,243,246,249,252,352,355,358,463,486,490,493,500,520,523,526,565,578,581,584,616,624,634,637,707,710,741,746,749,756,759,762,827,837,840,843,926,932,935,983,996,999,1002,1140,1143,1160,1165,1168,1171,1174,1320,1323,1326,1329,1332,1335,1487,1494,1497,1500,1503,1666,1669,1692,1695,1698,1701,1807,1822,1827,1831,1861,1864,2228,2266,2269,2272,2344,2347,2360,2381,2386,2389,2402,2414,2418,2425,2440,2445,2448,2451,2514,2554,2557,2562,2571,2676,2692,2763,2766,2906,2924,2929,2936,3106,3128,3133,3141,3305,3323,3328,3331,3334,3384,3399,3403,3406,3412,3419,3469,3477,3494,3497,3500,3503,3613,3620,3624,3627,3669,3677,3687,3690,3693,3696,3795,3799,3806,3844,3852,3858,3881,3884,3901,3904,4063,4066,4263,4267,4270,4274,4287,4350,4358,4376,4413,4428,4431,4570,4576,4579,4987,4993,4997,5000,5003,5037,5046,5049,5067,5070,5089,5092,5098,5102,5105,5109,5116,5119,5197,5217,5220,5265,5268,5353,5359,5362,5936,5942,5946,5949,5952,6035,6052,6066,6089,6092,6228,6231,6234,7143,7146,7670,7674,7699,7753,7764,7819,7832,7847,7850,7853,7915,7932,7975,7983,7989,8014,8062,8074,8077,9094,9100,9106,9110,9113,9116,9220],[10,11,12],"p",{},"To process an image, you first need to obtain it. In everyday life, we can capture photos using devices like cameras and smartphones, and store them on a hard drive in a certain format.\nSimilarly, when performing image processing in a computer program, it is also necessary to obtain image data in a specific way, store it in an appropriate container using a certain data type, and then display it to the user in some form.\nTherefore, this chapter will cover the loading, storage, and output of image data, including reading images and videos, creating and using image storage containers, and saving processed results in the form of images or videos.",[14,15,17],"h3",{"id":16},"image-storage-container","Image storage container",[10,19,20,21,25,26,29,30,33],{},"Unlike the images we see in daily life, digital images are stored in computers in the form of matrices. Each element in the matrix is used to describe some kind of information in the image, such as brightness, color, etc., as shown in Figure 2-1.\nThe essence of digital image processing is the process of extracting deeper information from these matrix data through a series of operations. Therefore, the first step in learning image processing is to master how to manipulate these matrix data.\nFor readers familiar with C++ programming, strings are typically stored as the ",[22,23,24],"code",{},"string"," type, and integers as the ",[22,27,28],{},"int"," type. Similarly, OpenCV provides a ",[22,31,32],{},"Mat"," class for storing matrix data.\nThis section will provide a detailed introduction to the usage of the Mat class and the operations it supports. By studying this, you will be able to flexibly use variables of the Mat type in your programs.",[10,35,36],{},[37,38],"img",{"alt":39,"src":40},"alt text","https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776084345222.webp",[42,43,45],"h4",{"id":44},"introduction-to-the-mat-class","Introduction to the Mat Class",[10,47,48],{},"In early versions of OpenCV 1.0, images were stored using a C language structure called IplImage. As a result, it can still be seen in some older OpenCV tutorials.",[10,50,51,52,55,56,58],{},"However, the ",[22,53,54],{},"IplImage"," type has a clear drawback — it requires the user to manually release memory. If there are still unreleased ",[22,57,54],{}," variables when the program ends, it will lead to memory leaks.",[10,60,61],{},"As OpenCV continues to evolve, the library has introduced a C++ interface and provides the Mat class for data storage. The Mat class uses an automatic memory management mechanism, effectively solving the problem of memory release. When a variable is no longer in use, the memory it occupies is automatically freed.",[10,63,64],{},"The Mat class is used to store matrix-type data, including vectors, matrices, as well as grayscale images and color images.",[10,66,67],{},"Structurally, the Mat class consists of two parts: a matrix header and a pointer to the actual data. The matrix header contains information such as the matrix size, storage method, data address, and reference count. The size of the matrix header is fixed and does not change with the matrix dimensions.",[10,69,70],{},"In the vast majority of cases, the matrix header occupies far less space than the matrix data itself. Therefore, during image copying and transmission, the primary overhead comes from the data portion.",[10,72,73,74,76],{},"To solve this problem, when copying or passing images, OpenCV does not copy the full data — it only copies the matrix header and the pointer to the data. Therefore, when creating a ",[22,75,32],{}," object, you can first create the matrix header and then assign data to it. The specific method is shown in Listing 2-1.",[78,79,84],"pre",{"className":80,"code":81,"language":82,"meta":83,"style":83},"language-cpp shiki shiki-themes github-light github-dark","cv::Mat a;                      // 创建一个名为 a 的矩阵头\na = cv::imread(\"test.jpg\");    // 读取图像数据，使 a 指向图像像素数据\ncv::Mat b = a;                 // 复制矩阵头，并命名为 b\n","cpp","",[22,85,86,103,135],{"__ignoreMap":83},[87,88,91,95,99],"span",{"class":89,"line":90},"line",1,[87,92,94],{"class":93},"sScJk","cv",[87,96,98],{"class":97},"sVt8B","::Mat a;",[87,100,102],{"class":101},"sJ8bj","                      // 创建一个名为 a 的矩阵头\n",[87,104,106,109,113,116,119,122,125,129,132],{"class":89,"line":105},2,[87,107,108],{"class":97},"a ",[87,110,112],{"class":111},"szBVR","=",[87,114,115],{"class":93}," cv",[87,117,118],{"class":97},"::",[87,120,121],{"class":93},"imread",[87,123,124],{"class":97},"(",[87,126,128],{"class":127},"sZZnC","\"test.jpg\"",[87,130,131],{"class":97},");",[87,133,134],{"class":101},"    // 读取图像数据，使 a 指向图像像素数据\n",[87,136,138,140,143,145,148],{"class":89,"line":137},3,[87,139,94],{"class":93},[87,141,142],{"class":97},"::Mat b ",[87,144,112],{"class":111},[87,146,147],{"class":97}," a;",[87,149,150],{"class":101},"                 // 复制矩阵头，并命名为 b\n",[10,152,153,154,157,158,160,161,163,164,167,168,170,171,173,174,176,177,179,180,170,182,184],{},"The code above first creates a matrix header named ",[22,155,156],{},"a",", then reads an image and makes the matrix pointer in ",[22,159,156],{}," point to the pixel data of that image. Finally, it copies the matrix header of ",[22,162,156],{}," to ",[22,165,166],{},"b",".\nIt is important to note that although ",[22,169,156],{}," and ",[22,172,166],{}," each have their own independent matrix headers, their matrix pointers point to the same block of data. Therefore, modifying the data through either matrix header will also change the data accessed by the other matrix header.\nAdditionally, when variable ",[22,175,156],{}," is deleted, ",[22,178,166],{}," does not become empty data; the underlying matrix data is only truly released when both ",[22,181,156],{},[22,183,166],{}," have been freed.\nThis is because a reference count is maintained in the matrix header, which records how many objects are currently sharing the same block of data. The data is only released when the reference count drops to zero.",[10,186,187],{},"Tip: Using reference counting to release stored content is a common approach in C++. This method prevents program crashes that could occur if data is deleted while still being referenced by a variable, while also significantly reducing the memory footprint during program execution.",[10,189,190],{},"Next, we will explain the data types that can be stored in the Mat class. According to the official Mat class inheritance diagram shown in Figure 2-2, we can see that the data types that can be stored in the Mat class include double, float, uchar, unsigned char, as well as custom templates.",[10,192,193],{},[37,194],{"alt":39,"src":195},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776084574108.webp",[10,197,198],{},"We can declare a Mat class variable that stores a specified type using the method shown in Code Listing 2-2.",[78,200,202],{"className":80,"code":201,"language":82,"meta":83,"style":83},"cv::Mat A = cv::Mat_\u003Cdouble>(3, 3);  // 创建一个 3×3 的 double 类型矩阵\n",[22,203,204],{"__ignoreMap":83},[87,205,206,208,211,213,215,217,220,223,226,229,233,236,238,240],{"class":89,"line":90},[87,207,94],{"class":93},[87,209,210],{"class":97},"::Mat A ",[87,212,112],{"class":111},[87,214,115],{"class":93},[87,216,118],{"class":97},[87,218,219],{"class":93},"Mat_",[87,221,222],{"class":97},"\u003C",[87,224,225],{"class":111},"double",[87,227,228],{"class":97},">(",[87,230,232],{"class":231},"sj4cs","3",[87,234,235],{"class":97},", ",[87,237,232],{"class":231},[87,239,131],{"class":97},[87,241,242],{"class":101},"  // 创建一个 3×3 的 double 类型矩阵\n",[10,244,245],{},"Since the Mat class in OpenCV is primarily used to store image data, the range of pixel values directly affects image quality. Using 8-bit unsigned integers to store 16-bit image data can cause severe color distortion and even data errors.",[10,247,248],{},"Additionally, compilers with different bit widths may define data type lengths differently. To prevent program issues caused by inconsistent variable bit widths across different platforms or environments, OpenCV standardizes data types.",[10,250,251],{},"Therefore, OpenCV defines a dedicated data type system based on the number of bits used to store numeric variables. Table 2-1 lists the commonly used data types in OpenCV and their value ranges.",[253,254,255,271],"table",{},[256,257,258],"thead",{},[259,260,261,265,268],"tr",{},[262,263,264],"th",{},"Data Type",[262,266,267],{},"Specific type",[262,269,270],{},"value range",[272,273,274,286,297,308,319,330,341],"tbody",{},[259,275,276,280,283],{},[277,278,279],"td",{},"CV_8U",[277,281,282],{},"8-bit unsigned integer",[277,284,285],{},"0 ～ 255",[259,287,288,291,294],{},[277,289,290],{},"CV_8S",[277,292,293],{},"8-bit signed integer",[277,295,296],{},"-128 ～ 127",[259,298,299,302,305],{},[277,300,301],{},"CV_16U",[277,303,304],{},"16-bit unsigned integer",[277,306,307],{},"0 ～ 65535",[259,309,310,313,316],{},[277,311,312],{},"CV_16S",[277,314,315],{},"16-bit signed integer",[277,317,318],{},"-32768 ～ 32767",[259,320,321,324,327],{},[277,322,323],{},"CV_32S",[277,325,326],{},"32-bit signed integer",[277,328,329],{},"-2147483648 ～ 2147483647",[259,331,332,335,338],{},[277,333,334],{},"CV_32F",[277,336,337],{},"32-bit floating point number",[277,339,340],{},"-FLT_MAX ～ FLT_MAX，INF，NaN",[259,342,343,346,349],{},[277,344,345],{},"CV_64F",[277,347,348],{},"64-bit floating-point number",[277,350,351],{},"-DBL_MAX ～ DBL_MAX，INF，NaN",[10,353,354],{},"Data types alone are not sufficient to fully describe image data; the number of image channels also needs to be defined. For example, a grayscale image is single-channel data, while a color image is typically 3-channel (RGB) or 4-channel (such as RGBA) data.",[10,356,357],{},"To meet this requirement, OpenCV defines channel count identifiers: C1, C2, C3, and C4, representing single-channel, dual-channel, three-channel, and four-channel respectively.\nSince each data type may correspond to a different number of channels, OpenCV combines the \"data type\" and \"number of channels\" to fully describe the image data type. For example:\nCV_8UC1: represents 8-bit unsigned, single-channel data, typically used for grayscale images.\nCV_8UC3: Represents 8-bit unsigned, three-channel data, typically used for color images.\nWe can create a Mat object with a specified data type and number of channels using the method shown in Code Listing 2-3.",[78,359,361],{"className":80,"code":360,"language":82,"meta":83,"style":83},"cv::Mat a(640, 480, CV_8UC3);  // 创建一个 640×480 的 3 通道矩阵（用于彩色图像）\n\ncv::Mat b(3, 3, CV_8UC1);      // 创建一个 3×3 的 8 位无符号单通道矩阵\n\ncv::Mat c(3, 3, CV_8U);        // 创建单通道矩阵，C1 标识可以省略\n",[22,362,363,394,400,429,434],{"__ignoreMap":83},[87,364,365,367,369,371,374,376,379,381,384,386,389,391],{"class":89,"line":90},[87,366,94],{"class":93},[87,368,118],{"class":97},[87,370,32],{"class":93},[87,372,373],{"class":93}," a",[87,375,124],{"class":97},[87,377,378],{"class":231},"640",[87,380,235],{"class":97},[87,382,383],{"class":231},"480",[87,385,235],{"class":97},[87,387,388],{"class":93},"CV_8UC3",[87,390,131],{"class":97},[87,392,393],{"class":101},"  // 创建一个 640×480 的 3 通道矩阵（用于彩色图像）\n",[87,395,396],{"class":89,"line":105},[87,397,399],{"emptyLinePlaceholder":398},true,"\n",[87,401,402,404,406,408,411,413,415,417,419,421,424,426],{"class":89,"line":137},[87,403,94],{"class":93},[87,405,118],{"class":97},[87,407,32],{"class":93},[87,409,410],{"class":93}," b",[87,412,124],{"class":97},[87,414,232],{"class":231},[87,416,235],{"class":97},[87,418,232],{"class":231},[87,420,235],{"class":97},[87,422,423],{"class":93},"CV_8UC1",[87,425,131],{"class":97},[87,427,428],{"class":101},"      // 创建一个 3×3 的 8 位无符号单通道矩阵\n",[87,430,432],{"class":89,"line":431},4,[87,433,399],{"emptyLinePlaceholder":398},[87,435,437,439,441,443,446,448,450,452,454,456,458,460],{"class":89,"line":436},5,[87,438,94],{"class":93},[87,440,118],{"class":97},[87,442,32],{"class":93},[87,444,445],{"class":93}," c",[87,447,124],{"class":97},[87,449,232],{"class":231},[87,451,235],{"class":97},[87,453,232],{"class":231},[87,455,235],{"class":97},[87,457,279],{"class":93},[87,459,131],{"class":97},[87,461,462],{"class":101},"        // 创建单通道矩阵，C1 标识可以省略\n",[10,464,465,466,170,469,471,472,474,475,477,478,481,482,485],{},"Although both ",[22,467,468],{},"uchar",[22,470,279],{}," represent 8-bit unsigned integers in a 64-bit compiler, there is a strict distinction between them: ",[22,473,279],{}," can only be used as a data type identifier within the ",[22,476,32],{}," class. Using ",[22,479,480],{}," Mat_\u003CCV_8U>(3,3)"," or ",[22,483,484],{},"Mat a(3,3,uchar)"," will result in a creation error.",[42,487,489],{"id":488},"mat-class-construction-and-assignment","Mat Class Construction and Assignment",[10,491,492],{},"The previous section introduced three methods for constructing Mat class variables, but the latter two did not initialize the variables with values. This section will focus on how to flexibly construct and assign values to Mat class variables. According to the OpenCV source code definition, there are over 20 ways to construct the Mat class. However, in many simple everyday applications, most of these complex construction methods are not particularly useful. Therefore, this book emphasizes the construction and assignment methods that the author commonly uses in learning and project development.",[10,494,495,499],{},[496,497,498],"em",{},"1. Construction of the Mat Class","\n(1) Using the default constructor (see Code Listing 2-4)",[78,501,503],{"className":80,"code":502,"language":82,"meta":83,"style":83},"cv::Mat::Mat();\n",[22,504,505],{"__ignoreMap":83},[87,506,507,509,511,513,515,517],{"class":89,"line":90},[87,508,94],{"class":93},[87,510,118],{"class":97},[87,512,32],{"class":93},[87,514,118],{"class":97},[87,516,32],{"class":93},[87,518,519],{"class":97},"();\n",[10,521,522],{},"Using Code Listing 2-4, a Mat class is constructed with the default constructor. This construction method does not require any input parameters. When assigning values to the variable later, it automatically determines the matrix type and size, enabling flexible storage. It is commonly used to store read image data and the output results of certain function operations.",[10,524,525],{},"(2) Construct based on the input matrix size and type (see Code Listing 2-5)",[78,527,529],{"className":80,"code":528,"language":82,"meta":83,"style":83},"cv::Mat::Mat(int rows,\n             int cols,\n             int type);\n",[22,530,531,550,558],{"__ignoreMap":83},[87,532,533,535,537,539,541,543,545,547],{"class":89,"line":90},[87,534,94],{"class":93},[87,536,118],{"class":97},[87,538,32],{"class":93},[87,540,118],{"class":97},[87,542,32],{"class":93},[87,544,124],{"class":97},[87,546,28],{"class":111},[87,548,549],{"class":97}," rows,\n",[87,551,552,555],{"class":89,"line":105},[87,553,554],{"class":111},"             int",[87,556,557],{"class":97}," cols,\n",[87,559,560,562],{"class":89,"line":137},[87,561,554],{"class":111},[87,563,564],{"class":97}," type);\n",[566,567,568,572,575],"ul",{},[569,570,571],"li",{},"rows: Number of rows in the constructed matrix.",[569,573,574],{},"cols: The number of columns in the matrix.",[569,576,577],{},"type: In addition to CV_8UC1, CV_64FC4, and other 1-to-4 channel types, it also provides parameters for more channels. A multi-channel matrix can be constructed using n in CV_8UC(n), where n can be up to 512.",[10,579,580],{},"We have seen this constructor in the previous post as well. It constructs the matrix by specifying the number of rows, columns, and the data type for storage. This definition is clear, intuitive, and easy to read. It is commonly used when the data size and type are clearly known, such as for a camera's intrinsic matrix or an object's rotation matrix.\nThere is a variation of the method for constructing a Mat class using the input matrix dimensions and data type, which assigns values by combining rows and columns into a Size() structure. Code Listing 2-6 provides the prototype for this construction method.",[10,582,583],{},"Code Listing 2-6 Constructing a Mat class using the Size() structure",[78,585,587],{"className":80,"code":586,"language":82,"meta":83,"style":83},"cv::Mat::Mat(Size size(),\n             int type);\n",[22,588,589,610],{"__ignoreMap":83},[87,590,591,593,595,597,599,601,604,607],{"class":89,"line":90},[87,592,94],{"class":93},[87,594,118],{"class":97},[87,596,32],{"class":93},[87,598,118],{"class":97},[87,600,32],{"class":93},[87,602,603],{"class":97},"(Size ",[87,605,606],{"class":93},"size",[87,608,609],{"class":97},"(),\n",[87,611,612,614],{"class":89,"line":105},[87,613,554],{"class":111},[87,615,564],{"class":97},[566,617,618,621],{},[569,619,620],{},"size: The dimension of a two-dimensional array variable, assigned using Size(cols, rows).",[569,622,623],{},"type: Consistent with the parameters in Code Listing 2-5.",[10,625,626,627,630,631,633],{},"When constructing a Mat class in this way, be especially careful: in the ",[22,628,629],{},"Size()"," structure, the order of rows and columns is reversed compared to the method in Code Listing 2-5. When using ",[22,632,629],{}," (see Code Listing 2-7), the column comes first and the row comes after. If you don't pay attention, the Mat class will still be constructed successfully, but when you need to access a specific element, you may not realize the rows and columns are swapped, which could lead to array out-of-bounds errors.",[10,635,636],{},"Code Listing 2-7 Example of constructing a Mat using the Size structure",[78,638,640],{"className":80,"code":639,"language":82,"meta":83,"style":83},"cv::Mat a(Size(480, 640), CV_8UC1);   // 构造一个行为640、列为480的单通道矩阵\ncv::Mat b(Size(480, 640), CV_32FC3); // 构造一个行为640、列为480的3通道矩阵\n",[22,641,642,675],{"__ignoreMap":83},[87,643,644,646,648,650,652,654,657,659,661,663,665,668,670,672],{"class":89,"line":90},[87,645,94],{"class":93},[87,647,118],{"class":97},[87,649,32],{"class":93},[87,651,373],{"class":93},[87,653,124],{"class":97},[87,655,656],{"class":93},"Size",[87,658,124],{"class":97},[87,660,383],{"class":231},[87,662,235],{"class":97},[87,664,378],{"class":231},[87,666,667],{"class":97},"), ",[87,669,423],{"class":93},[87,671,131],{"class":97},[87,673,674],{"class":101},"   // 构造一个行为640、列为480的单通道矩阵\n",[87,676,677,679,681,683,685,687,689,691,693,695,697,699,702,704],{"class":89,"line":105},[87,678,94],{"class":93},[87,680,118],{"class":97},[87,682,32],{"class":93},[87,684,410],{"class":93},[87,686,124],{"class":97},[87,688,656],{"class":93},[87,690,124],{"class":97},[87,692,383],{"class":231},[87,694,235],{"class":97},[87,696,378],{"class":231},[87,698,667],{"class":97},[87,700,701],{"class":93},"CV_32FC3",[87,703,131],{"class":97},[87,705,706],{"class":101}," // 构造一个行为640、列为480的3通道矩阵\n",[10,708,709],{},"(3) Construct using an existing matrix (see Code Listing 2-8)",[78,711,713],{"className":80,"code":712,"language":82,"meta":83,"style":83},"cv::Mat::Mat(const Mat &m);\n",[22,714,715],{"__ignoreMap":83},[87,716,717,719,721,723,725,727,729,732,735,738],{"class":89,"line":90},[87,718,94],{"class":93},[87,720,118],{"class":97},[87,722,32],{"class":93},[87,724,118],{"class":97},[87,726,32],{"class":93},[87,728,124],{"class":97},[87,730,731],{"class":111},"const",[87,733,734],{"class":97}," Mat ",[87,736,737],{"class":111},"&",[87,739,740],{"class":97},"m);\n",[566,742,743],{},[569,744,745],{},"m: The Mat class matrix data that has already been constructed.",[10,747,748],{},"This construction method is very simple and can create a variable that stores the same content as an existing Mat class variable. Note that this method only copies the matrix header of the Mat class, and the matrix pointer points to the same address. Therefore, if the data in the matrix is modified through one Mat class variable, the data in the other variable will also change.",[10,750,751,752,755],{},"Tip: If you want to create two identical Mat classes that do not affect each other, you can use the ",[22,753,754],{},"clone()"," function.",[10,757,758],{},"If the matrix to be constructed is smaller than the existing matrix and stores a subset of its content, the method in Code Listing 2-9 can be used to build it.",[10,760,761],{},"Listing 2-9 Constructing a subclass of an existing Mat class",[78,763,765],{"className":80,"code":764,"language":82,"meta":83,"style":83},"cv::Mat::Mat(const Mat &m,\n             const Range &rowRange,\n             const Range &colRange = Range::all());\n",[22,766,767,790,803],{"__ignoreMap":83},[87,768,769,771,773,775,777,779,781,783,785,787],{"class":89,"line":90},[87,770,94],{"class":93},[87,772,118],{"class":97},[87,774,32],{"class":93},[87,776,118],{"class":97},[87,778,32],{"class":93},[87,780,124],{"class":97},[87,782,731],{"class":111},[87,784,734],{"class":97},[87,786,737],{"class":111},[87,788,789],{"class":97},"m,\n",[87,791,792,795,798,800],{"class":89,"line":105},[87,793,794],{"class":111},"             const",[87,796,797],{"class":97}," Range ",[87,799,737],{"class":111},[87,801,802],{"class":97},"rowRange,\n",[87,804,805,807,809,811,814,816,819,821,824],{"class":89,"line":137},[87,806,794],{"class":111},[87,808,797],{"class":97},[87,810,737],{"class":111},[87,812,813],{"class":97},"colRange ",[87,815,112],{"class":111},[87,817,818],{"class":93}," Range",[87,820,118],{"class":97},[87,822,823],{"class":93},"all",[87,825,826],{"class":97},"());\n",[566,828,829,831,834],{},[569,830,745],{},[569,832,833],{},"rowRange: The range of rows to extract from the existing matrix. It is a Range variable. For example, extracting rows 2 through 5 can be expressed as Range(2,5).",[569,835,836],{},"colRange: The range of columns to extract from the existing matrix. It is a Range variable. For example, extracting from column 2 to column 5 can be expressed as Range(2,5). When no value is entered, all columns are extracted.",[10,838,839],{},"This method is mainly used for taking screenshots within the original image. However, it's important to note that the Mat class constructed in this way shares the same data with the existing Mat class — meaning if the data in one Mat class changes, the other will change accordingly.",[10,841,842],{},"Code Listing 2-10: Extracting a sub-Mat class from the original Mat",[78,844,846],{"className":80,"code":845,"language":82,"meta":83,"style":83},"cv::Mat b(a, Range(2, 5), Range(2, 5));  // 从a中截取部分数据构造b\ncv::Mat c(a, Range(2, 5));               // 默认最后一个参数构造c\n",[22,847,848,895],{"__ignoreMap":83},[87,849,850,852,854,856,858,860,862,864,867,869,872,874,877,879,881,883,885,887,889,892],{"class":89,"line":90},[87,851,94],{"class":93},[87,853,118],{"class":97},[87,855,32],{"class":93},[87,857,410],{"class":93},[87,859,124],{"class":97},[87,861,156],{"class":93},[87,863,235],{"class":97},[87,865,866],{"class":93},"Range",[87,868,124],{"class":97},[87,870,871],{"class":231},"2",[87,873,235],{"class":97},[87,875,876],{"class":231},"5",[87,878,667],{"class":97},[87,880,866],{"class":93},[87,882,124],{"class":97},[87,884,871],{"class":231},[87,886,235],{"class":97},[87,888,876],{"class":231},[87,890,891],{"class":97},"));",[87,893,894],{"class":101},"  // 从a中截取部分数据构造b\n",[87,896,897,899,901,903,905,907,909,911,913,915,917,919,921,923],{"class":89,"line":105},[87,898,94],{"class":93},[87,900,118],{"class":97},[87,902,32],{"class":93},[87,904,445],{"class":93},[87,906,124],{"class":97},[87,908,156],{"class":93},[87,910,235],{"class":97},[87,912,866],{"class":93},[87,914,124],{"class":97},[87,916,871],{"class":231},[87,918,235],{"class":97},[87,920,876],{"class":231},[87,922,891],{"class":97},[87,924,925],{"class":101},"               // 默认最后一个参数构造c\n",[10,927,928,931],{},[496,929,930],{},"2. Assigning values to the Mat class","\nOnce the Mat class is constructed, the variable does not yet contain any data; data needs to be assigned to it. For different scenarios, OpenCV 4.1 provides multiple assignment methods. The following explains how to assign values to Mat class variables.",[10,933,934],{},"(1) Assignment during construction (see Code Listing 2-11)",[78,936,938],{"className":80,"code":937,"language":82,"meta":83,"style":83},"cv::Mat::Mat(int rows,\n             int cols,\n             int type,\n             const Scalar &s);\n",[22,939,940,958,964,971],{"__ignoreMap":83},[87,941,942,944,946,948,950,952,954,956],{"class":89,"line":90},[87,943,94],{"class":93},[87,945,118],{"class":97},[87,947,32],{"class":93},[87,949,118],{"class":97},[87,951,32],{"class":93},[87,953,124],{"class":97},[87,955,28],{"class":111},[87,957,549],{"class":97},[87,959,960,962],{"class":89,"line":105},[87,961,554],{"class":111},[87,963,557],{"class":97},[87,965,966,968],{"class":89,"line":137},[87,967,554],{"class":111},[87,969,970],{"class":97}," type,\n",[87,972,973,975,978,980],{"class":89,"line":431},[87,974,794],{"class":111},[87,976,977],{"class":97}," Scalar ",[87,979,737],{"class":111},[87,981,982],{"class":97},"s);\n",[566,984,985,988,990,993],{},[569,986,987],{},"rows: The number of rows in the matrix.",[569,989,574],{},[569,991,992],{},"type: The type of data to be stored.",[569,994,995],{},"s: Parameter variable for assigning values to each pixel in the matrix, for example Scalar(0,0,255).",[10,997,998],{},"This method assigns values during construction (see Code Listing 2-12), by placing the value to assign to each element into a Scalar structure. Note that this approach assigns the same value to every element in the image; for example, Scalar(0,0,255) assigns the three channel values of each pixel to 0, 0, and 255 respectively.",[10,1000,1001],{},"Code Listing 2-12 Example of assignment during construction",[78,1003,1005],{"className":80,"code":1004,"language":82,"meta":83,"style":83},"cv::Mat a(2, 2, CV_8UC3, cv::Scalar(0, 0, 255));  // 创建一个3通道矩阵，每个像素都是0,0,255\ncv::Mat b(2, 2, CV_8UC2, cv::Scalar(0, 255));     // 创建一个2通道矩阵，每个像素都是0,255\ncv::Mat c(2, 2, CV_8UC1, cv::Scalar(255));         // 创建一个单通道矩阵，每个像素都是255\n",[22,1006,1007,1057,1101],{"__ignoreMap":83},[87,1008,1009,1011,1013,1015,1017,1019,1021,1023,1025,1027,1029,1031,1033,1035,1038,1040,1043,1045,1047,1049,1052,1054],{"class":89,"line":90},[87,1010,94],{"class":93},[87,1012,118],{"class":97},[87,1014,32],{"class":93},[87,1016,373],{"class":93},[87,1018,124],{"class":97},[87,1020,871],{"class":231},[87,1022,235],{"class":97},[87,1024,871],{"class":231},[87,1026,235],{"class":97},[87,1028,388],{"class":93},[87,1030,235],{"class":97},[87,1032,94],{"class":93},[87,1034,118],{"class":97},[87,1036,1037],{"class":93},"Scalar",[87,1039,124],{"class":97},[87,1041,1042],{"class":231},"0",[87,1044,235],{"class":97},[87,1046,1042],{"class":231},[87,1048,235],{"class":97},[87,1050,1051],{"class":231},"255",[87,1053,891],{"class":97},[87,1055,1056],{"class":101},"  // 创建一个3通道矩阵，每个像素都是0,0,255\n",[87,1058,1059,1061,1063,1065,1067,1069,1071,1073,1075,1077,1080,1082,1084,1086,1088,1090,1092,1094,1096,1098],{"class":89,"line":105},[87,1060,94],{"class":93},[87,1062,118],{"class":97},[87,1064,32],{"class":93},[87,1066,410],{"class":93},[87,1068,124],{"class":97},[87,1070,871],{"class":231},[87,1072,235],{"class":97},[87,1074,871],{"class":231},[87,1076,235],{"class":97},[87,1078,1079],{"class":93},"CV_8UC2",[87,1081,235],{"class":97},[87,1083,94],{"class":93},[87,1085,118],{"class":97},[87,1087,1037],{"class":93},[87,1089,124],{"class":97},[87,1091,1042],{"class":231},[87,1093,235],{"class":97},[87,1095,1051],{"class":231},[87,1097,891],{"class":97},[87,1099,1100],{"class":101},"     // 创建一个2通道矩阵，每个像素都是0,255\n",[87,1102,1103,1105,1107,1109,1111,1113,1115,1117,1119,1121,1123,1125,1127,1129,1131,1133,1135,1137],{"class":89,"line":137},[87,1104,94],{"class":93},[87,1106,118],{"class":97},[87,1108,32],{"class":93},[87,1110,445],{"class":93},[87,1112,124],{"class":97},[87,1114,871],{"class":231},[87,1116,235],{"class":97},[87,1118,871],{"class":231},[87,1120,235],{"class":97},[87,1122,423],{"class":93},[87,1124,235],{"class":97},[87,1126,94],{"class":93},[87,1128,118],{"class":97},[87,1130,1037],{"class":93},[87,1132,124],{"class":97},[87,1134,1051],{"class":231},[87,1136,891],{"class":97},[87,1138,1139],{"class":101},"         // 创建一个单通道矩阵，每个像素都是255\n",[10,1141,1142],{},"We add a breakpoint before the program's return statement for debugging, and use Image Watch to inspect the data in each Mat class variable. The results are shown in Figure 2-3, confirming that the matrix has been successfully constructed and assigned values.",[10,1144,1145,1146,1149,1150,1153,1154,1156,1157,1159],{},"Tip: The number of variables in the Scalar structure must correspond to the number of channels defined. If the number of variables in the Scalar structure exceeds the number of channels, the values beyond the channel count will not be read. For example, after executing ",[22,1147,1148],{},"a(2,2,CV_8UC2,Scalar(0,0,255))",", each pixel value will be ",[22,1151,1152],{},"(0,0)",", and ",[22,1155,1051],{}," will not be read. If the number of variables in the Scalar structure is less than the number of channels, the missing values will be filled with ",[22,1158,1042],{},".",[10,1161,1162],{},[37,1163],{"alt":39,"src":1164},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776086526691.webp",[10,1166,1167],{},"(2) Assignment using enumeration",[10,1169,1170],{},"This assignment method lists all the elements in the matrix one by one and assigns them to the Mat class in the form of a data stream. The specific assignment format is shown in Code Listing 2-13.",[10,1172,1173],{},"Code Listing 2-13 Example of Assignment Using Enumeration",[78,1175,1177],{"className":80,"code":1176,"language":82,"meta":83,"style":83},"cv::Mat a = (cv::Mat_\u003Cint>(3, 3) \u003C\u003C 1, 2, 3, 4, 5, 6, 7, 8, 9);\ncv::Mat b = (cv::Mat_\u003Cdouble>(2, 3) \u003C\u003C 1.0, 2.1, 3.2, 4.0, 5.1, 6.2);\n",[22,1178,1179,1258],{"__ignoreMap":83},[87,1180,1181,1183,1186,1188,1191,1193,1195,1197,1199,1201,1203,1205,1207,1209,1212,1215,1218,1220,1222,1224,1226,1228,1231,1233,1235,1237,1240,1242,1245,1247,1250,1252,1255],{"class":89,"line":90},[87,1182,94],{"class":93},[87,1184,1185],{"class":97},"::Mat a ",[87,1187,112],{"class":111},[87,1189,1190],{"class":97}," (",[87,1192,94],{"class":93},[87,1194,118],{"class":97},[87,1196,219],{"class":93},[87,1198,222],{"class":97},[87,1200,28],{"class":111},[87,1202,228],{"class":97},[87,1204,232],{"class":231},[87,1206,235],{"class":97},[87,1208,232],{"class":231},[87,1210,1211],{"class":97},") ",[87,1213,1214],{"class":111},"\u003C\u003C",[87,1216,1217],{"class":231}," 1",[87,1219,235],{"class":97},[87,1221,871],{"class":231},[87,1223,235],{"class":97},[87,1225,232],{"class":231},[87,1227,235],{"class":97},[87,1229,1230],{"class":231},"4",[87,1232,235],{"class":97},[87,1234,876],{"class":231},[87,1236,235],{"class":97},[87,1238,1239],{"class":231},"6",[87,1241,235],{"class":97},[87,1243,1244],{"class":231},"7",[87,1246,235],{"class":97},[87,1248,1249],{"class":231},"8",[87,1251,235],{"class":97},[87,1253,1254],{"class":231},"9",[87,1256,1257],{"class":97},");\n",[87,1259,1260,1262,1264,1266,1268,1270,1272,1274,1276,1278,1280,1282,1284,1286,1288,1290,1293,1295,1298,1300,1303,1305,1308,1310,1313,1315,1318],{"class":89,"line":105},[87,1261,94],{"class":93},[87,1263,142],{"class":97},[87,1265,112],{"class":111},[87,1267,1190],{"class":97},[87,1269,94],{"class":93},[87,1271,118],{"class":97},[87,1273,219],{"class":93},[87,1275,222],{"class":97},[87,1277,225],{"class":111},[87,1279,228],{"class":97},[87,1281,871],{"class":231},[87,1283,235],{"class":97},[87,1285,232],{"class":231},[87,1287,1211],{"class":97},[87,1289,1214],{"class":111},[87,1291,1292],{"class":231}," 1.0",[87,1294,235],{"class":97},[87,1296,1297],{"class":231},"2.1",[87,1299,235],{"class":97},[87,1301,1302],{"class":231},"3.2",[87,1304,235],{"class":97},[87,1306,1307],{"class":231},"4.0",[87,1309,235],{"class":97},[87,1311,1312],{"class":231},"5.1",[87,1314,235],{"class":97},[87,1316,1317],{"class":231},"6.2",[87,1319,1257],{"class":97},[10,1321,1322],{},"The first line of code creates a 3×3 matrix containing the integers 1 through 9. The matrix is filled row by row: the first row stores 1, 2, 3; the second row stores 4, 5, 6; and the third row stores 7, 8, 9. The second line of code creates a 2×3 matrix, which is filled in the same way as matrix a.",[10,1324,1325],{},"Tip: When using the enumeration method, the number of input data items must match the number of matrix elements. For example, in the first line of code in Listing 2-13, if only 8 numbers (1 through 8) are entered, the assignment process will result in an error. Therefore, this method is typically used when the matrix data is relatively small.",[10,1327,1328],{},"(3) Assigning values using a loop",[10,1330,1331],{},"Similar to the enumeration assignment method, the loop assignment method also assigns values to each element in the matrix. However, it does not require assignment at the time of variable declaration, and it allows assigning values to any part of the matrix. The specific assignment format is shown in Code Listing 2-14.",[10,1333,1334],{},"Code Listing 2-14 Example of Assignment Using a Loop",[78,1336,1338],{"className":80,"code":1337,"language":82,"meta":83,"style":83},"\ncv::Mat c = cv::Mat(3, 3, CV_8UC1);  // 定义一个3*3的矩阵\nfor (int i = 0; i \u003C c.rows; i++)    // 矩阵行数循环\n{\n    for (int j = 0; j \u003C c.cols; j++)  // 矩阵列数循环\n    {\n        c.at\u003Cuchar>(i, j) = i + j;\n    }\n}\n\n",[22,1339,1340,1344,1373,1407,1412,1443,1449,1475,1481],{"__ignoreMap":83},[87,1341,1342],{"class":89,"line":90},[87,1343,399],{"emptyLinePlaceholder":398},[87,1345,1346,1348,1351,1353,1355,1357,1359,1361,1363,1365,1367,1370],{"class":89,"line":105},[87,1347,94],{"class":93},[87,1349,1350],{"class":97},"::Mat c ",[87,1352,112],{"class":111},[87,1354,115],{"class":93},[87,1356,118],{"class":97},[87,1358,32],{"class":93},[87,1360,124],{"class":97},[87,1362,232],{"class":231},[87,1364,235],{"class":97},[87,1366,232],{"class":231},[87,1368,1369],{"class":97},", CV_8UC1);",[87,1371,1372],{"class":101},"  // 定义一个3*3的矩阵\n",[87,1374,1375,1378,1380,1382,1385,1387,1390,1393,1395,1398,1401,1404],{"class":89,"line":137},[87,1376,1377],{"class":111},"for",[87,1379,1190],{"class":97},[87,1381,28],{"class":111},[87,1383,1384],{"class":97}," i ",[87,1386,112],{"class":111},[87,1388,1389],{"class":231}," 0",[87,1391,1392],{"class":97},"; i ",[87,1394,222],{"class":111},[87,1396,1397],{"class":97}," c.rows; i",[87,1399,1400],{"class":111},"++",[87,1402,1403],{"class":97},")",[87,1405,1406],{"class":101},"    // 矩阵行数循环\n",[87,1408,1409],{"class":89,"line":431},[87,1410,1411],{"class":97},"{\n",[87,1413,1414,1417,1419,1421,1424,1426,1428,1431,1433,1436,1438,1440],{"class":89,"line":436},[87,1415,1416],{"class":111},"    for",[87,1418,1190],{"class":97},[87,1420,28],{"class":111},[87,1422,1423],{"class":97}," j ",[87,1425,112],{"class":111},[87,1427,1389],{"class":231},[87,1429,1430],{"class":97},"; j ",[87,1432,222],{"class":111},[87,1434,1435],{"class":97}," c.cols; j",[87,1437,1400],{"class":111},[87,1439,1403],{"class":97},[87,1441,1442],{"class":101},"  // 矩阵列数循环\n",[87,1444,1446],{"class":89,"line":1445},6,[87,1447,1448],{"class":97},"    {\n",[87,1450,1452,1455,1457,1459,1462,1465,1467,1469,1472],{"class":89,"line":1451},7,[87,1453,1454],{"class":97},"        c.at",[87,1456,222],{"class":111},[87,1458,468],{"class":97},[87,1460,1461],{"class":111},">",[87,1463,1464],{"class":97},"(i, j) ",[87,1466,112],{"class":111},[87,1468,1384],{"class":97},[87,1470,1471],{"class":111},"+",[87,1473,1474],{"class":97}," j;\n",[87,1476,1478],{"class":89,"line":1477},8,[87,1479,1480],{"class":97},"    }\n",[87,1482,1484],{"class":89,"line":1483},9,[87,1485,1486],{"class":97},"}\n",[10,1488,1489,1490,1493],{},"The code above also creates a 3×3 matrix, assigning a value to each element in the matrix using a for loop. It is important to note that when assigning values to each element of the matrix, the variable type declared in the assignment function must match the variable type defined for the matrix. That is, the variable types in line 1 and line 6 of Code Listing 2-14 must be the same. If line 6 is changed to ",[22,1491,1492],{},"c.at\u003Cdouble>",", the program will report an error and fail to assign the values.",[10,1495,1496],{},"(4) Class method assignment",[10,1498,1499],{},"The Mat class provides methods for quick assignment, allowing initialization of specified matrices. For example, generating identity matrices, diagonal matrices, or matrices where all elements are 0 or 1. The specific usage is shown in Code Listing 2-15.",[10,1501,1502],{},"Code Listing 2-15 Example of Assignment Using Class Methods",[78,1504,1506],{"className":80,"code":1505,"language":82,"meta":83,"style":83},"cv::Mat a = cv::Mat::eye(3, 3, CV_8UC1);\ncv::Mat b = (cv::Mat_\u003Cint>(1, 3) \u003C\u003C 1, 2, 3);\ncv::Mat c = cv::Mat::diag(b);\ncv::Mat d = cv::Mat::ones(3, 3, CV_8UC1);\ncv::Mat e = cv::Mat::zeros(4, 2, CV_8UC3);\n",[22,1507,1508,1538,1583,1605,1635],{"__ignoreMap":83},[87,1509,1510,1512,1514,1516,1518,1520,1522,1524,1527,1529,1531,1533,1535],{"class":89,"line":90},[87,1511,94],{"class":93},[87,1513,1185],{"class":97},[87,1515,112],{"class":111},[87,1517,115],{"class":93},[87,1519,118],{"class":97},[87,1521,32],{"class":93},[87,1523,118],{"class":97},[87,1525,1526],{"class":93},"eye",[87,1528,124],{"class":97},[87,1530,232],{"class":231},[87,1532,235],{"class":97},[87,1534,232],{"class":231},[87,1536,1537],{"class":97},", CV_8UC1);\n",[87,1539,1540,1542,1544,1546,1548,1550,1552,1554,1556,1558,1560,1563,1565,1567,1569,1571,1573,1575,1577,1579,1581],{"class":89,"line":105},[87,1541,94],{"class":93},[87,1543,142],{"class":97},[87,1545,112],{"class":111},[87,1547,1190],{"class":97},[87,1549,94],{"class":93},[87,1551,118],{"class":97},[87,1553,219],{"class":93},[87,1555,222],{"class":97},[87,1557,28],{"class":111},[87,1559,228],{"class":97},[87,1561,1562],{"class":231},"1",[87,1564,235],{"class":97},[87,1566,232],{"class":231},[87,1568,1211],{"class":97},[87,1570,1214],{"class":111},[87,1572,1217],{"class":231},[87,1574,235],{"class":97},[87,1576,871],{"class":231},[87,1578,235],{"class":97},[87,1580,232],{"class":231},[87,1582,1257],{"class":97},[87,1584,1585,1587,1589,1591,1593,1595,1597,1599,1602],{"class":89,"line":137},[87,1586,94],{"class":93},[87,1588,1350],{"class":97},[87,1590,112],{"class":111},[87,1592,115],{"class":93},[87,1594,118],{"class":97},[87,1596,32],{"class":93},[87,1598,118],{"class":97},[87,1600,1601],{"class":93},"diag",[87,1603,1604],{"class":97},"(b);\n",[87,1606,1607,1609,1612,1614,1616,1618,1620,1622,1625,1627,1629,1631,1633],{"class":89,"line":431},[87,1608,94],{"class":93},[87,1610,1611],{"class":97},"::Mat d ",[87,1613,112],{"class":111},[87,1615,115],{"class":93},[87,1617,118],{"class":97},[87,1619,32],{"class":93},[87,1621,118],{"class":97},[87,1623,1624],{"class":93},"ones",[87,1626,124],{"class":97},[87,1628,232],{"class":231},[87,1630,235],{"class":97},[87,1632,232],{"class":231},[87,1634,1537],{"class":97},[87,1636,1637,1639,1642,1644,1646,1648,1650,1652,1655,1657,1659,1661,1663],{"class":89,"line":436},[87,1638,94],{"class":93},[87,1640,1641],{"class":97},"::Mat e ",[87,1643,112],{"class":111},[87,1645,115],{"class":93},[87,1647,118],{"class":97},[87,1649,32],{"class":93},[87,1651,118],{"class":97},[87,1653,1654],{"class":93},"zeros",[87,1656,124],{"class":97},[87,1658,1230],{"class":231},[87,1660,235],{"class":97},[87,1662,871],{"class":231},[87,1664,1665],{"class":97},", CV_8UC3);\n",[10,1667,1668],{},"The role of each function in the code above and the meaning of its parameters are explained as follows:",[566,1670,1671,1674,1680,1683],{},[569,1672,1673],{},"eye(): Constructs an identity matrix. The first two parameters are the number of rows and columns of the matrix, and the third parameter is the data type and number of channels for the matrix storage. If the number of rows and columns are not equal, the values at the main diagonal positions (1,1), (2,2), (3,3), etc. are set to 1.",[569,1675,1676,1679],{},[22,1677,1678],{},"diag()",": Constructs a diagonal matrix. Its parameter must be a one-dimensional variable of type Mat, used to store the values of the diagonal elements.",[569,1681,1682],{},"ones(): Constructs a matrix of all ones, with the same parameter meanings as eye().",[569,1684,1685,1688,1689,1159],{},[22,1686,1687],{},"zeros()",": Constructs a matrix filled entirely with zeros. The parameters have the same meaning as those in ",[22,1690,1691],{},"eye()",[10,1693,1694],{},"(5) Using arrays for assignment",[10,1696,1697],{},"This method is similar to the enumeration method, but it allows changing the number of channels in the Mat class matrix based on requirements, and can be seen as an extension of the enumeration method. Code Listing 2-16 shows the assignment format for this method.",[10,1699,1700],{},"Code Listing 2-16 Example of assignment using arrays",[78,1702,1704],{"className":80,"code":1703,"language":82,"meta":83,"style":83},"float a[8] = {5, 6, 7, 8, 1, 2, 3, 4};\ncv::Mat b = cv::Mat(2, 2, CV_32FC2, a);\ncv::Mat c = cv::Mat(2, 4, CV_32FC1, a);\n",[22,1705,1706,1757,1782],{"__ignoreMap":83},[87,1707,1708,1711,1714,1716,1719,1721,1724,1726,1728,1730,1732,1734,1736,1738,1740,1742,1744,1746,1748,1750,1752,1754],{"class":89,"line":90},[87,1709,1710],{"class":111},"float",[87,1712,1713],{"class":97}," a[",[87,1715,1249],{"class":231},[87,1717,1718],{"class":97},"] ",[87,1720,112],{"class":111},[87,1722,1723],{"class":97}," {",[87,1725,876],{"class":231},[87,1727,235],{"class":97},[87,1729,1239],{"class":231},[87,1731,235],{"class":97},[87,1733,1244],{"class":231},[87,1735,235],{"class":97},[87,1737,1249],{"class":231},[87,1739,235],{"class":97},[87,1741,1562],{"class":231},[87,1743,235],{"class":97},[87,1745,871],{"class":231},[87,1747,235],{"class":97},[87,1749,232],{"class":231},[87,1751,235],{"class":97},[87,1753,1230],{"class":231},[87,1755,1756],{"class":97},"};\n",[87,1758,1759,1761,1763,1765,1767,1769,1771,1773,1775,1777,1779],{"class":89,"line":105},[87,1760,94],{"class":93},[87,1762,142],{"class":97},[87,1764,112],{"class":111},[87,1766,115],{"class":93},[87,1768,118],{"class":97},[87,1770,32],{"class":93},[87,1772,124],{"class":97},[87,1774,871],{"class":231},[87,1776,235],{"class":97},[87,1778,871],{"class":231},[87,1780,1781],{"class":97},", CV_32FC2, a);\n",[87,1783,1784,1786,1788,1790,1792,1794,1796,1798,1800,1802,1804],{"class":89,"line":137},[87,1785,94],{"class":93},[87,1787,1350],{"class":97},[87,1789,112],{"class":111},[87,1791,115],{"class":93},[87,1793,118],{"class":97},[87,1795,32],{"class":93},[87,1797,124],{"class":97},[87,1799,871],{"class":231},[87,1801,235],{"class":97},[87,1803,1230],{"class":231},[87,1805,1806],{"class":97},", CV_32FC1, a);\n",[10,1808,1809,1810,1812,1813,1815,1816,170,1818,1821],{},"This assignment method first stores the variables to be placed into a ",[22,1811,32],{}," object into an array. Then, by setting the dimensions and number of channels of the ",[22,1814,32],{}," matrix, the array variables are split into a matrix. This splitting method allows the number of channels in the matrix to be freely defined. When the number of elements in the matrix is greater than the amount of data in the array, the matrix will be filled with the value 1.0737418e+08. When the number of elements in the matrix is less than the amount of data in the array, after the matrix assignment is complete, the remaining data in the array will not be assigned. The process of assigning from the array to the matrix first assigns all channels of the first element in the matrix sequentially, then moves on to assign the next element. To better understand this process, the defined matrices ",[22,1817,166],{},[22,1819,1820],{},"c"," are shown in Figure 2-4.",[10,1823,1824],{},[37,1825],{"alt":39,"src":1826},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776086715064.webp",[42,1828,1830],{"id":1829},"operations-supported-by-the-mat-class","Operations supported by the Mat class",[10,1832,1833,1834,1836,1837,1839,1840,1842,1843,1845,1846,235,1848,235,1851,235,1854,1857,1858,1860],{},"When processing data, it is often necessary to perform addition, subtraction, multiplication, and division operations. For example, operations like image filtering and enhancement require pixel-level arithmetic. To facilitate these computations, variables of the ",[22,1835,32],{}," class support matrix arithmetic operations. This means that when using ",[22,1838,32],{}," variables, they can be treated as ordinary matrices. For instance, multiplying a ",[22,1841,32],{}," variable by a constant follows the same rules as matrix-scalar multiplication. When performing arithmetic between a ",[22,1844,32],{}," object and a constant, the standard arithmetic operators (",[22,1847,1471],{},[22,1849,1850],{},"-",[22,1852,1853],{},"*",[22,1855,1856],{},"/",") can be used directly. Listing 2-17 provides an example program demonstrating addition, subtraction, multiplication, and division between a ",[22,1859,32],{}," variable and a constant.",[10,1862,1863],{},"Code Listing 2-17: Arithmetic operations on the Mat class",[78,1865,1867],{"className":80,"code":1866,"language":82,"meta":83,"style":83},"cv::Mat a = (cv::Mat_\u003Cint>(3, 3) \u003C\u003C 1, 2, 3, 4, 5, 6, 7, 8, 9);\ncv::Mat b = (cv::Mat_\u003Cint>(3, 3) \u003C\u003C 1, 2, 3, 4, 5, 6, 7, 8, 9);\ncv::Mat c = (cv::Mat_\u003Cdouble>(3, 3) \u003C\u003C 1.0, 2.1, 3.2, 4.0, 5.1, 6.2, 2, 2, 2);\ncv::Mat d = (cv::Mat_\u003Cdouble>(3, 3) \u003C\u003C 1.0, 2.1, 3.2, 4.0, 5.1, 6.2, 2, 2, 2);\ncv::Mat e, f, g, h, i;\ne = a + b;\nf = c - d;\ng = 2 * a;\nh = d / 2.0;\ni = a - 1;\n",[22,1868,1869,1937,2005,2073,2141,2148,2163,2178,2194,2212],{"__ignoreMap":83},[87,1870,1871,1873,1875,1877,1879,1881,1883,1885,1887,1889,1891,1893,1895,1897,1899,1901,1903,1905,1907,1909,1911,1913,1915,1917,1919,1921,1923,1925,1927,1929,1931,1933,1935],{"class":89,"line":90},[87,1872,94],{"class":93},[87,1874,1185],{"class":97},[87,1876,112],{"class":111},[87,1878,1190],{"class":97},[87,1880,94],{"class":93},[87,1882,118],{"class":97},[87,1884,219],{"class":93},[87,1886,222],{"class":97},[87,1888,28],{"class":111},[87,1890,228],{"class":97},[87,1892,232],{"class":231},[87,1894,235],{"class":97},[87,1896,232],{"class":231},[87,1898,1211],{"class":97},[87,1900,1214],{"class":111},[87,1902,1217],{"class":231},[87,1904,235],{"class":97},[87,1906,871],{"class":231},[87,1908,235],{"class":97},[87,1910,232],{"class":231},[87,1912,235],{"class":97},[87,1914,1230],{"class":231},[87,1916,235],{"class":97},[87,1918,876],{"class":231},[87,1920,235],{"class":97},[87,1922,1239],{"class":231},[87,1924,235],{"class":97},[87,1926,1244],{"class":231},[87,1928,235],{"class":97},[87,1930,1249],{"class":231},[87,1932,235],{"class":97},[87,1934,1254],{"class":231},[87,1936,1257],{"class":97},[87,1938,1939,1941,1943,1945,1947,1949,1951,1953,1955,1957,1959,1961,1963,1965,1967,1969,1971,1973,1975,1977,1979,1981,1983,1985,1987,1989,1991,1993,1995,1997,1999,2001,2003],{"class":89,"line":105},[87,1940,94],{"class":93},[87,1942,142],{"class":97},[87,1944,112],{"class":111},[87,1946,1190],{"class":97},[87,1948,94],{"class":93},[87,1950,118],{"class":97},[87,1952,219],{"class":93},[87,1954,222],{"class":97},[87,1956,28],{"class":111},[87,1958,228],{"class":97},[87,1960,232],{"class":231},[87,1962,235],{"class":97},[87,1964,232],{"class":231},[87,1966,1211],{"class":97},[87,1968,1214],{"class":111},[87,1970,1217],{"class":231},[87,1972,235],{"class":97},[87,1974,871],{"class":231},[87,1976,235],{"class":97},[87,1978,232],{"class":231},[87,1980,235],{"class":97},[87,1982,1230],{"class":231},[87,1984,235],{"class":97},[87,1986,876],{"class":231},[87,1988,235],{"class":97},[87,1990,1239],{"class":231},[87,1992,235],{"class":97},[87,1994,1244],{"class":231},[87,1996,235],{"class":97},[87,1998,1249],{"class":231},[87,2000,235],{"class":97},[87,2002,1254],{"class":231},[87,2004,1257],{"class":97},[87,2006,2007,2009,2011,2013,2015,2017,2019,2021,2023,2025,2027,2029,2031,2033,2035,2037,2039,2041,2043,2045,2047,2049,2051,2053,2055,2057,2059,2061,2063,2065,2067,2069,2071],{"class":89,"line":137},[87,2008,94],{"class":93},[87,2010,1350],{"class":97},[87,2012,112],{"class":111},[87,2014,1190],{"class":97},[87,2016,94],{"class":93},[87,2018,118],{"class":97},[87,2020,219],{"class":93},[87,2022,222],{"class":97},[87,2024,225],{"class":111},[87,2026,228],{"class":97},[87,2028,232],{"class":231},[87,2030,235],{"class":97},[87,2032,232],{"class":231},[87,2034,1211],{"class":97},[87,2036,1214],{"class":111},[87,2038,1292],{"class":231},[87,2040,235],{"class":97},[87,2042,1297],{"class":231},[87,2044,235],{"class":97},[87,2046,1302],{"class":231},[87,2048,235],{"class":97},[87,2050,1307],{"class":231},[87,2052,235],{"class":97},[87,2054,1312],{"class":231},[87,2056,235],{"class":97},[87,2058,1317],{"class":231},[87,2060,235],{"class":97},[87,2062,871],{"class":231},[87,2064,235],{"class":97},[87,2066,871],{"class":231},[87,2068,235],{"class":97},[87,2070,871],{"class":231},[87,2072,1257],{"class":97},[87,2074,2075,2077,2079,2081,2083,2085,2087,2089,2091,2093,2095,2097,2099,2101,2103,2105,2107,2109,2111,2113,2115,2117,2119,2121,2123,2125,2127,2129,2131,2133,2135,2137,2139],{"class":89,"line":431},[87,2076,94],{"class":93},[87,2078,1611],{"class":97},[87,2080,112],{"class":111},[87,2082,1190],{"class":97},[87,2084,94],{"class":93},[87,2086,118],{"class":97},[87,2088,219],{"class":93},[87,2090,222],{"class":97},[87,2092,225],{"class":111},[87,2094,228],{"class":97},[87,2096,232],{"class":231},[87,2098,235],{"class":97},[87,2100,232],{"class":231},[87,2102,1211],{"class":97},[87,2104,1214],{"class":111},[87,2106,1292],{"class":231},[87,2108,235],{"class":97},[87,2110,1297],{"class":231},[87,2112,235],{"class":97},[87,2114,1302],{"class":231},[87,2116,235],{"class":97},[87,2118,1307],{"class":231},[87,2120,235],{"class":97},[87,2122,1312],{"class":231},[87,2124,235],{"class":97},[87,2126,1317],{"class":231},[87,2128,235],{"class":97},[87,2130,871],{"class":231},[87,2132,235],{"class":97},[87,2134,871],{"class":231},[87,2136,235],{"class":97},[87,2138,871],{"class":231},[87,2140,1257],{"class":97},[87,2142,2143,2145],{"class":89,"line":436},[87,2144,94],{"class":93},[87,2146,2147],{"class":97},"::Mat e, f, g, h, i;\n",[87,2149,2150,2153,2155,2158,2160],{"class":89,"line":1445},[87,2151,2152],{"class":97},"e ",[87,2154,112],{"class":111},[87,2156,2157],{"class":97}," a ",[87,2159,1471],{"class":111},[87,2161,2162],{"class":97}," b;\n",[87,2164,2165,2168,2170,2173,2175],{"class":89,"line":1451},[87,2166,2167],{"class":97},"f ",[87,2169,112],{"class":111},[87,2171,2172],{"class":97}," c ",[87,2174,1850],{"class":111},[87,2176,2177],{"class":97}," d;\n",[87,2179,2180,2183,2185,2188,2191],{"class":89,"line":1477},[87,2181,2182],{"class":97},"g ",[87,2184,112],{"class":111},[87,2186,2187],{"class":231}," 2",[87,2189,2190],{"class":111}," *",[87,2192,2193],{"class":97}," a;\n",[87,2195,2196,2199,2201,2204,2206,2209],{"class":89,"line":1483},[87,2197,2198],{"class":97},"h ",[87,2200,112],{"class":111},[87,2202,2203],{"class":97}," d ",[87,2205,1856],{"class":111},[87,2207,2208],{"class":231}," 2.0",[87,2210,2211],{"class":97},";\n",[87,2213,2215,2218,2220,2222,2224,2226],{"class":89,"line":2214},10,[87,2216,2217],{"class":97},"i ",[87,2219,112],{"class":111},[87,2221,2157],{"class":97},[87,2223,1850],{"class":111},[87,2225,1217],{"class":231},[87,2227,2211],{"class":97},[10,2229,2230,2231,2233,2234,2236,2237,170,2239,2241,2242,2244,2245,2247,2248,2250,2251,2253,2254,2256,2257,2259,2260,2262,2263,2265],{},"It is important to note that when performing addition or subtraction between two ",[22,2232,32],{}," class variables, the data types of both matrices must be identical. For example, two ",[22,2235,32],{}," class variables storing ",[22,2238,28],{},[22,2240,225],{}," data types respectively cannot be added or subtracted. Unlike regular multiplication and division, when a constant is used in an operation with a ",[22,2243,32],{}," class variable, the resulting data type retains that of the ",[22,2246,32],{}," class variable. For instance, if a ",[22,2249,225],{}," constant is used with an ",[22,2252,28],{}," type ",[22,2255,32],{}," class variable, the final result will still be of type ",[22,2258,28],{},". In the last line of code in Listing 2-17, subtracting a constant from a ",[22,2261,32],{}," class variable means that every element in the ",[22,2264,32],{}," class variable is reduced by that constant.",[10,2267,2268],{},"When performing convolution operations on an image, two matrices need to be multiplied. OpenCV not only provides multiplication operations for two Mat class matrices, but also defines the inner product and element-wise multiplication of two matrices. Code Listing 2-18 shows the code implementation for multiplying two Mat class matrices.",[10,2270,2271],{},"Code Listing 2-18 Multiplication of two Mat class matrices",[78,2273,2275],{"className":80,"code":2274,"language":82,"meta":83,"style":83},"cv::Mat j, m;\ndouble k;\nj = c * d;  //乘法\nk = a.dot(b);  //内积\nm = a.mul(b);   //对位乘法\n",[22,2276,2277,2284,2291,2308,2327],{"__ignoreMap":83},[87,2278,2279,2281],{"class":89,"line":90},[87,2280,94],{"class":93},[87,2282,2283],{"class":97},"::Mat j, m;\n",[87,2285,2286,2288],{"class":89,"line":105},[87,2287,225],{"class":111},[87,2289,2290],{"class":97}," k;\n",[87,2292,2293,2296,2298,2300,2302,2305],{"class":89,"line":137},[87,2294,2295],{"class":97},"j ",[87,2297,112],{"class":111},[87,2299,2172],{"class":97},[87,2301,1853],{"class":111},[87,2303,2304],{"class":97}," d;",[87,2306,2307],{"class":101},"  //乘法\n",[87,2309,2310,2313,2315,2318,2321,2324],{"class":89,"line":431},[87,2311,2312],{"class":97},"k ",[87,2314,112],{"class":111},[87,2316,2317],{"class":97}," a.",[87,2319,2320],{"class":93},"dot",[87,2322,2323],{"class":97},"(b);",[87,2325,2326],{"class":101},"  //内积\n",[87,2328,2329,2332,2334,2336,2339,2341],{"class":89,"line":436},[87,2330,2331],{"class":97},"m ",[87,2333,112],{"class":111},[87,2335,2317],{"class":97},[87,2337,2338],{"class":93},"mul",[87,2340,2323],{"class":97},[87,2342,2343],{"class":101},"   //对位乘法\n",[10,2345,2346],{},"The matrix definition and assignment in Listing 2-18 are the same as in Listing 2-17. In the code, two Mat class variables and one double variable are defined, implementing multiplication, inner product, and element-wise multiplication of the two Mat class matrices, respectively.",[10,2348,2349,2350,2353,2354,2356,2357],{},"The ",[22,2351,2352],{},"@"," operator in line 3 represents the mathematical product of two matrices. For example, given two matrices A₃ₓ₃ and B₃ₓ₃, the result of the ",[22,2355,2352],{}," operation is matrix C₃ₓ₃, where each element in C₃ₓ₃ is expressed as:\n",[37,2358],{"alt":39,"src":2359},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776086843699.webp",[10,2361,2362,2363,2366,2367,2369,2370,2373,2374,2377,2378,2380],{},"It is important to note that the \"*\" operation requires the number of columns in the first Mat matrix to equal the number of rows in the second Mat matrix. Additionally, this operation requires the data type in the Mat class to be one of the following four types: CV_32FC1, CV_64FC1, CV_32FC2, or CV_64FC2. In other words, for a two-dimensional Mat matrix, the stored data type must be either float or double.\nLine 4 in Code Listing 2-18 represents the inner product of two Mat class matrices. Based on the output, the ",[22,2364,2365],{},"dot()"," method returns a ",[22,2368,225],{}," type variable. This operation computes the dot product of a row vector and a column vector. For example, given two vectors d = ",[87,2371,2372],{},"d₁ d₂ d₃"," and e = ",[87,2375,2376],{},"e₁ e₂ e₃",", the result of the ",[22,2379,2365],{}," method is:",[10,2382,2383],{},[37,2384],{"alt":39,"src":2385},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776086868251.webp",[10,2387,2388],{},"It is important to note that the two input Mat matrices must have the same number of elements. However, regardless of the dimensions of the two input Mat matrices, both matrices will be expanded into a row vector and a column vector. Therefore, the result of the dot() operation is always a double-type variable.",[10,2390,2391,2392,2395,2396,2398,2399],{},"Line 5 in Code Listing 2-18 represents the element-wise product of two Mat class matrices. Based on the output, it can be seen that the result of the ",[22,2393,2394],{},"mul()"," method is also a Mat class matrix. For two matrices A₃ₓ₃ and B₃ₓ₃, each element in the resulting matrix C₃ₓ₃ from the ",[22,2397,2394],{}," method can be expressed as:\n",[37,2400],{"alt":39,"src":2401},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776086882221.webp",[10,2403,2404,2405,2407,2408,2410,2411,2413],{},"It is important to note that, unlike the first two multiplication operations, the data stored in the two Mat matrices involved in the ",[22,2406,2394],{}," method can be of any type, provided they are the same, and the default output data type remains consistent with the two Mat matrices. In the field of image processing, the commonly used data type is ",[22,2409,279],{},", which ranges from 0 to 255. When two relatively large integers are multiplied together, overflow can occur, resulting in an output value of 255. Therefore, when using the ",[22,2412,2394],{}," method, care must be taken to prevent data overflow.",[42,2415,2417],{"id":2416},"reading-mat-class-elements","Reading Mat class elements",[10,2419,2420,2421,2424],{},"For reading and modifying Mat class matrices, we have already introduced how to use the ",[22,2422,2423],{},"at"," method to assign values to each element of the matrix in the section on matrix loop assignment. This is just one of the many ways OpenCV provides to read matrix elements. This section will detail how to read elements from a Mat class matrix and modify their values.",[10,2426,2427,2428,2430,2431,2433,2434,2436,2437,2439],{},"Before learning how to read the elements of a ",[22,2429,32],{}," class matrix, you first need to understand how ",[22,2432,32],{}," class variables are stored in a computer. A multi-channel ",[22,2435,32],{}," matrix is similar to three-dimensional data, but a computer's storage space is two-dimensional. Therefore, when a ",[22,2438,32],{}," matrix is stored in a computer, the three-dimensional data is flattened into two-dimensional data: the data for each channel of the first element is stored first, followed by the data for each channel of the second element. The elements in each row are stored in this manner. Thus, if we find the starting position of each element, we can locate the data for each channel within that element. Figure 2-5 illustrates the storage method of a three-channel matrix, where consecutive blue, green, and red squares represent the three channels of each element.",[10,2441,2442],{},[37,2443],{"alt":39,"src":2444},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776087165988.webp",[10,2446,2447],{},"Now that we understand how Mat class variables are stored, let's look at the properties of the Mat class. Table 2-2 lists the commonly used properties of the Mat class matrix, along with a detailed explanation of each property's purpose.",[10,2449,2450],{},"Table 2-2 Common attributes of the Mat class matrix",[253,2452,2453,2464],{},[256,2454,2455],{},[259,2456,2457,2461],{},[262,2458,2460],{"align":2459},"left","attribute",[262,2462,2463],{"align":2459},"effect",[272,2465,2466,2474,2482,2490,2498,2506],{},[259,2467,2468,2471],{},[277,2469,2470],{"align":2459},"cols",[277,2472,2473],{"align":2459},"The number of columns in the matrix",[259,2475,2476,2479],{},[277,2477,2478],{"align":2459},"rows",[277,2480,2481],{"align":2459},"Number of rows in the matrix",[259,2483,2484,2487],{},[277,2485,2486],{"align":2459},"step",[277,2488,2489],{"align":2459},"Effective width of the matrix in bytes",[259,2491,2492,2495],{},[277,2493,2494],{"align":2459},"elemSize()",[277,2496,2497],{"align":2459},"Number of bytes per element",[259,2499,2500,2503],{},[277,2501,2502],{"align":2459},"total()",[277,2504,2505],{"align":2459},"Number of elements in a matrix",[259,2507,2508,2511],{},[277,2509,2510],{"align":2459},"channels()",[277,2512,2513],{"align":2459},"The number of channels in the matrix",[10,2515,2516,2517,2519,2520,2522,2523,2525,2526,2528,2529,2532,2533,2535,2536,2538,2539,2541,2542,2544,2545,2547,2548,2550,2551,2553],{},"Combining these attributes can yield most properties of a ",[22,2518,32],{}," matrix. For example, combining the ",[22,2521,2486],{}," attribute with the ",[22,2524,2470],{}," attribute can calculate the number of bytes occupied by each element. Further combining this with the ",[22,2527,2510],{}," attribute reveals the number of bytes per channel, thereby indicating the type of data stored in the matrix. The following example illustrates the use of each attribute: define a matrix using ",[22,2530,2531],{},"Mat(3, 4, CV_32FC3)",". In this case, the number of channels ",[22,2534,2510],{}," is 3; the number of columns ",[22,2537,2470],{}," is 4; the number of rows ",[22,2540,2478],{}," is 3; the total number of elements in the matrix is 3 × 4, resulting in 12; the number of bytes per element is 32/8 × ",[22,2543,2510],{},", which in this example gives 12; the effective length in bytes, ",[22,2546,2486],{},", is ",[22,2549,2494],{}," × ",[22,2552,2470],{},", resulting in 48 in this example.",[10,2555,2556],{},"Common methods for reading elements of the Mat class matrix include reading via the at method, reading via the pointer ptr, reading via iterators, and reading via matrix element address positioning. The following provides a detailed introduction to these four reading methods.",[10,2558,2559],{},[496,2560,2561],{},"1. Reading elements from a Mat class matrix using the at method",[10,2563,2564,2565,2567,2568,2570],{},"Reading matrix elements using the ",[22,2566,2423],{}," method is divided into methods for single-channel and multi-channel access. Code Listing 2-19 provides the code for reading single-channel matrix elements via the ",[22,2569,2423],{}," method.\nCode Listing 2-19 Reading a Single-Channel Matrix Element of the Mat Class Using the at Method",[78,2572,2574],{"className":80,"code":2573,"language":82,"meta":83,"style":83},"cv::Mat a = (cv::Mat_\u003Cuchar>(3, 3) \u003C\u003C 1, 2, 3, 4, 5, 6, 7, 8, 9);\nint value = (int)a.at\u003Cuchar>(0, 0);\n",[22,2575,2576,2644],{"__ignoreMap":83},[87,2577,2578,2580,2582,2584,2586,2588,2590,2592,2594,2596,2598,2600,2602,2604,2606,2608,2610,2612,2614,2616,2618,2620,2622,2624,2626,2628,2630,2632,2634,2636,2638,2640,2642],{"class":89,"line":90},[87,2579,94],{"class":93},[87,2581,1185],{"class":97},[87,2583,112],{"class":111},[87,2585,1190],{"class":97},[87,2587,94],{"class":93},[87,2589,118],{"class":97},[87,2591,219],{"class":93},[87,2593,222],{"class":97},[87,2595,468],{"class":93},[87,2597,228],{"class":97},[87,2599,232],{"class":231},[87,2601,235],{"class":97},[87,2603,232],{"class":231},[87,2605,1211],{"class":97},[87,2607,1214],{"class":111},[87,2609,1217],{"class":231},[87,2611,235],{"class":97},[87,2613,871],{"class":231},[87,2615,235],{"class":97},[87,2617,232],{"class":231},[87,2619,235],{"class":97},[87,2621,1230],{"class":231},[87,2623,235],{"class":97},[87,2625,876],{"class":231},[87,2627,235],{"class":97},[87,2629,1239],{"class":231},[87,2631,235],{"class":97},[87,2633,1244],{"class":231},[87,2635,235],{"class":97},[87,2637,1249],{"class":231},[87,2639,235],{"class":97},[87,2641,1254],{"class":231},[87,2643,1257],{"class":97},[87,2645,2646,2648,2651,2653,2655,2657,2660,2662,2664,2666,2668,2670,2672,2674],{"class":89,"line":105},[87,2647,28],{"class":111},[87,2649,2650],{"class":97}," value ",[87,2652,112],{"class":111},[87,2654,1190],{"class":97},[87,2656,28],{"class":111},[87,2658,2659],{"class":97},")a.at",[87,2661,222],{"class":111},[87,2663,468],{"class":97},[87,2665,1461],{"class":111},[87,2667,124],{"class":97},[87,2669,1042],{"class":231},[87,2671,235],{"class":97},[87,2673,1042],{"class":231},[87,2675,1257],{"class":97},[10,2677,2678,2679,2681,2682,2685,2686,2688,2689,2691],{},"When reading an element using the ",[22,2680,2423],{}," method, you need to append ",[22,2683,2684],{},"\"\u003Cdata type>\""," afterward. If the data type specified here does not match the data type defined for the matrix, an error will occur due to a data type mismatch. This method provides the coordinates of the element to be read in the form (row, column). It is important to note that if the matrix is defined with the ",[22,2687,468],{}," data type, the data must be explicitly cast to ",[22,2690,28],{}," type when outputting; otherwise, the output will not be an integer.",[10,2693,2694,2695,2697,2698,235,2701,235,2704,235,2707,235,2710,1153,2713,2716,2717,2719,2720,235,2722,2719,2725,235,2728,2719,2731,235,2734,2719,2737,235,2739,2719,2742,1153,2744,2719,2747,2749,2750,2752,2753,170,2756,2759,2760,2762],{},"Since a single-channel image is a two-dimensional matrix, you can access the element at a given position by providing the 2D planar coordinates at the end of the ",[22,2696,2423],{}," method. In a multi-channel matrix, each coordinate contains multiple data points, so a variable is introduced to represent these multiple data values for the same element. In OpenCV, for three-channel matrices, six types are defined to represent the three channel data of the same element: ",[22,2699,2700],{},"cv::Vec3b",[22,2702,2703],{},"cv::Vec3s",[22,2705,2706],{},"cv::Vec3w",[22,2708,2709],{},"cv::Vec3d",[22,2711,2712],{},"cv::Vec3f",[22,2714,2715],{},"cv::Vec3i",". From these six data types, a naming convention can be inferred: the number indicates the number of channels, and the final letter is an abbreviation of the data type — ",[22,2718,166],{}," for ",[22,2721,468],{},[22,2723,2724],{},"s",[22,2726,2727],{},"short",[22,2729,2730],{},"w",[22,2732,2733],{},"ushort",[22,2735,2736],{},"d",[22,2738,225],{},[22,2740,2741],{},"f",[22,2743,1710],{},[22,2745,2746],{},"i",[22,2748,28],{},". OpenCV also defines corresponding variable types for two-channel and four-channel matrices, following the same naming convention. For example, the ",[22,2751,468],{}," types for two and four channels are represented as ",[22,2754,2755],{},"cv::Vec2b",[22,2757,2758],{},"cv::Vec4b",", respectively. Listing 2-20 provides the implementation code for reading a multi-channel matrix using the ",[22,2761,2423],{}," method.",[10,2764,2765],{},"Code Listing 2-20 Reading multi-channel matrix elements of the Mat class using the at method",[78,2767,2769],{"className":80,"code":2768,"language":82,"meta":83,"style":83},"cv::Mat b(3, 4, CV_8UC3, cv::Scalar(0, 0, 1));\ncv::Vec3b vc3 = b.at\u003Ccv::Vec3b>(0, 0);\nint first = (int)vc3.val[0];\nint second = (int)vc3.val[1];\nint third = (int)vc3.val[2];\n",[22,2770,2771,2816,2847,2868,2887],{"__ignoreMap":83},[87,2772,2773,2775,2777,2779,2781,2783,2785,2787,2789,2791,2793,2795,2797,2799,2801,2803,2805,2807,2809,2811,2813],{"class":89,"line":90},[87,2774,94],{"class":93},[87,2776,118],{"class":97},[87,2778,32],{"class":93},[87,2780,410],{"class":93},[87,2782,124],{"class":97},[87,2784,232],{"class":231},[87,2786,235],{"class":97},[87,2788,1230],{"class":231},[87,2790,235],{"class":97},[87,2792,388],{"class":93},[87,2794,235],{"class":97},[87,2796,94],{"class":93},[87,2798,118],{"class":97},[87,2800,1037],{"class":93},[87,2802,124],{"class":97},[87,2804,1042],{"class":231},[87,2806,235],{"class":97},[87,2808,1042],{"class":231},[87,2810,235],{"class":97},[87,2812,1562],{"class":231},[87,2814,2815],{"class":97},"));\n",[87,2817,2818,2820,2823,2825,2828,2830,2832,2835,2837,2839,2841,2843,2845],{"class":89,"line":105},[87,2819,94],{"class":93},[87,2821,2822],{"class":97},"::Vec3b vc3 ",[87,2824,112],{"class":111},[87,2826,2827],{"class":97}," b.at",[87,2829,222],{"class":111},[87,2831,94],{"class":93},[87,2833,2834],{"class":97},"::Vec3b",[87,2836,1461],{"class":111},[87,2838,124],{"class":97},[87,2840,1042],{"class":231},[87,2842,235],{"class":97},[87,2844,1042],{"class":231},[87,2846,1257],{"class":97},[87,2848,2849,2851,2854,2856,2858,2860,2863,2865],{"class":89,"line":137},[87,2850,28],{"class":111},[87,2852,2853],{"class":97}," first ",[87,2855,112],{"class":111},[87,2857,1190],{"class":97},[87,2859,28],{"class":111},[87,2861,2862],{"class":97},")vc3.val[",[87,2864,1042],{"class":231},[87,2866,2867],{"class":97},"];\n",[87,2869,2870,2872,2875,2877,2879,2881,2883,2885],{"class":89,"line":431},[87,2871,28],{"class":111},[87,2873,2874],{"class":97}," second ",[87,2876,112],{"class":111},[87,2878,1190],{"class":97},[87,2880,28],{"class":111},[87,2882,2862],{"class":97},[87,2884,1562],{"class":231},[87,2886,2867],{"class":97},[87,2888,2889,2891,2894,2896,2898,2900,2902,2904],{"class":89,"line":436},[87,2890,28],{"class":111},[87,2892,2893],{"class":97}," third ",[87,2895,112],{"class":111},[87,2897,1190],{"class":97},[87,2899,28],{"class":111},[87,2901,2862],{"class":97},[87,2903,871],{"class":231},[87,2905,2867],{"class":97},[10,2907,2908,2909,2911,2912,2914,2915,2917,2918,2920,2921,2923],{},"When using multi-channel variable types, it is also important to ensure that the data variable type in the ",[22,2910,2423],{}," method corresponds to the data variable type of the matrix. Additionally, when inputting data for each channel with the ",[22,2913,2700],{}," type, the variable type must be explicitly cast to ",[22,2916,28],{},". However, if the data read by the ",[22,2919,2423],{}," method is directly assigned to a ",[22,2922,2715],{}," type variable, there is no need to perform a type cast when outputting data for each channel.",[10,2925,2926],{},[496,2927,2928],{},"2. Reading elements from a Mat class matrix using the pointer ptr",[10,2930,2931,2932,2935],{},"Earlier, we analyzed how Mat class matrices are stored in memory. The elements in each row of the matrix are stored contiguously. If we find the starting address of each row's elements, we can read elements at different positions within that row by moving the pointer backward or forward by a certain number of bits from the starting position. Code Listing 2-21 provides an implementation for reading Mat class matrix elements using the pointer ",[22,2933,2934],{},"ptr",".\nCode Listing 2-21 Reading Mat class matrix elements using pointer ptr",[78,2937,2939],{"className":80,"code":2938,"language":82,"meta":83,"style":83},"cv::Mat b(3, 4, CV_8UC3, cv::Scalar(0, 0, 1));\nfor (int i = 0; i \u003C b.rows; i++)\n{\n    uchar* ptr = b.ptr\u003Cuchar>(i);\n    for (int j = 0; j \u003C b.cols * b.channels(); j++)\n    {\n        cout \u003C\u003C (int)ptr[j] \u003C\u003C endl;\n    }\n}\n",[22,2940,2941,2985,3011,3015,3039,3075,3079,3098,3102],{"__ignoreMap":83},[87,2942,2943,2945,2947,2949,2951,2953,2955,2957,2959,2961,2963,2965,2967,2969,2971,2973,2975,2977,2979,2981,2983],{"class":89,"line":90},[87,2944,94],{"class":93},[87,2946,118],{"class":97},[87,2948,32],{"class":93},[87,2950,410],{"class":93},[87,2952,124],{"class":97},[87,2954,232],{"class":231},[87,2956,235],{"class":97},[87,2958,1230],{"class":231},[87,2960,235],{"class":97},[87,2962,388],{"class":93},[87,2964,235],{"class":97},[87,2966,94],{"class":93},[87,2968,118],{"class":97},[87,2970,1037],{"class":93},[87,2972,124],{"class":97},[87,2974,1042],{"class":231},[87,2976,235],{"class":97},[87,2978,1042],{"class":231},[87,2980,235],{"class":97},[87,2982,1562],{"class":231},[87,2984,2815],{"class":97},[87,2986,2987,2989,2991,2993,2995,2997,2999,3001,3003,3006,3008],{"class":89,"line":105},[87,2988,1377],{"class":111},[87,2990,1190],{"class":97},[87,2992,28],{"class":111},[87,2994,1384],{"class":97},[87,2996,112],{"class":111},[87,2998,1389],{"class":231},[87,3000,1392],{"class":97},[87,3002,222],{"class":111},[87,3004,3005],{"class":97}," b.rows; i",[87,3007,1400],{"class":111},[87,3009,3010],{"class":97},")\n",[87,3012,3013],{"class":89,"line":137},[87,3014,1411],{"class":97},[87,3016,3017,3020,3022,3025,3027,3030,3032,3034,3036],{"class":89,"line":431},[87,3018,3019],{"class":97},"    uchar",[87,3021,1853],{"class":111},[87,3023,3024],{"class":97}," ptr ",[87,3026,112],{"class":111},[87,3028,3029],{"class":97}," b.ptr",[87,3031,222],{"class":111},[87,3033,468],{"class":97},[87,3035,1461],{"class":111},[87,3037,3038],{"class":97},"(i);\n",[87,3040,3041,3043,3045,3047,3049,3051,3053,3055,3057,3060,3062,3065,3068,3071,3073],{"class":89,"line":436},[87,3042,1416],{"class":111},[87,3044,1190],{"class":97},[87,3046,28],{"class":111},[87,3048,1423],{"class":97},[87,3050,112],{"class":111},[87,3052,1389],{"class":231},[87,3054,1430],{"class":97},[87,3056,222],{"class":111},[87,3058,3059],{"class":97}," b.cols ",[87,3061,1853],{"class":111},[87,3063,3064],{"class":97}," b.",[87,3066,3067],{"class":93},"channels",[87,3069,3070],{"class":97},"(); j",[87,3072,1400],{"class":111},[87,3074,3010],{"class":97},[87,3076,3077],{"class":89,"line":1445},[87,3078,1448],{"class":97},[87,3080,3081,3084,3086,3088,3090,3093,3095],{"class":89,"line":1451},[87,3082,3083],{"class":97},"        cout ",[87,3085,1214],{"class":111},[87,3087,1190],{"class":97},[87,3089,28],{"class":111},[87,3091,3092],{"class":97},")ptr[j] ",[87,3094,1214],{"class":111},[87,3096,3097],{"class":97}," endl;\n",[87,3099,3100],{"class":89,"line":1477},[87,3101,1480],{"class":97},[87,3103,3104],{"class":89,"line":1483},[87,3105,1486],{"class":97},[10,3107,3108,3109,3111,3112,3114,3115,3117,3118,3121,3122,3124,3125,1159],{},"In the program, there is first a large loop that controls each row in the matrix. Then, a pointer of type ",[22,3110,468],{}," is defined. When defining it, the variable type of the ",[22,3113,32],{}," class matrix must be declared, and at the end of the definition, parentheses are used to specify which row of the ",[22,3116,32],{}," class matrix the pointer points to. The second loop controls the output of data from all channels in each row of the matrix. According to the storage format shown in Figure 2-5, the amount of data stored in each row is the product of the number of columns and the number of channels. That is, the pointer can move backward by ",[22,3119,3120],{},"cols × channels()"," positions, as shown in line 7 of the code, where the number of positions the pointer moves backward is given in brackets. The program provides a method for traversing every piece of data in a ",[22,3123,32],{}," class matrix using a loop. When we know which data needs to be accessed, we can directly access it by specifying the row number and the number of positions the pointer has moved. For example, when reading the third piece of data in the second row, it can be accessed directly via ",[22,3126,3127],{},"ptr[2]",[10,3129,3130],{},[496,3131,3132],{},"3. Accessing elements in a Mat class matrix via iterators",[10,3134,2349,3135,3137,3138,3140],{},[22,3136,32],{}," class variable is also a container variable, so it has iterators for accessing the data within the ",[22,3139,32],{}," class variable. Using iterators, you can traverse every element in the matrix. The code implementation is provided in Listing 2-22.\nCode Listing 2-22 Reading Mat Class Matrix Elements via Iterator",[78,3142,3144],{"className":80,"code":3143,"language":82,"meta":83,"style":83},"cv::MatIterator_\u003Cuchar> it = a.begin\u003Cuchar>();\ncv::MatIterator_\u003Cuchar> it_end = a.end\u003Cuchar>();\nfor (int i = 0; it != it_end; it++)\n{\n    cout \u003C\u003C (int)(*it) \u003C\u003C \" \";\n    if ((++i % a.cols) == 0)\n    {\n        cout \u003C\u003C endl;\n    }\n}\n",[22,3145,3146,3175,3203,3230,3234,3260,3285,3289,3297,3301],{"__ignoreMap":83},[87,3147,3148,3150,3153,3155,3157,3159,3162,3164,3167,3169,3171,3173],{"class":89,"line":90},[87,3149,94],{"class":93},[87,3151,3152],{"class":97},"::MatIterator_",[87,3154,222],{"class":111},[87,3156,468],{"class":97},[87,3158,1461],{"class":111},[87,3160,3161],{"class":97}," it ",[87,3163,112],{"class":111},[87,3165,3166],{"class":97}," a.begin",[87,3168,222],{"class":111},[87,3170,468],{"class":97},[87,3172,1461],{"class":111},[87,3174,519],{"class":97},[87,3176,3177,3179,3181,3183,3185,3187,3190,3192,3195,3197,3199,3201],{"class":89,"line":105},[87,3178,94],{"class":93},[87,3180,3152],{"class":97},[87,3182,222],{"class":111},[87,3184,468],{"class":97},[87,3186,1461],{"class":111},[87,3188,3189],{"class":97}," it_end ",[87,3191,112],{"class":111},[87,3193,3194],{"class":97}," a.end",[87,3196,222],{"class":111},[87,3198,468],{"class":97},[87,3200,1461],{"class":111},[87,3202,519],{"class":97},[87,3204,3205,3207,3209,3211,3213,3215,3217,3220,3223,3226,3228],{"class":89,"line":137},[87,3206,1377],{"class":111},[87,3208,1190],{"class":97},[87,3210,28],{"class":111},[87,3212,1384],{"class":97},[87,3214,112],{"class":111},[87,3216,1389],{"class":231},[87,3218,3219],{"class":97},"; it ",[87,3221,3222],{"class":111},"!=",[87,3224,3225],{"class":97}," it_end; it",[87,3227,1400],{"class":111},[87,3229,3010],{"class":97},[87,3231,3232],{"class":89,"line":431},[87,3233,1411],{"class":97},[87,3235,3236,3239,3241,3243,3245,3248,3250,3253,3255,3258],{"class":89,"line":436},[87,3237,3238],{"class":97},"    cout ",[87,3240,1214],{"class":111},[87,3242,1190],{"class":97},[87,3244,28],{"class":111},[87,3246,3247],{"class":97},")(",[87,3249,1853],{"class":111},[87,3251,3252],{"class":97},"it) ",[87,3254,1214],{"class":111},[87,3256,3257],{"class":127}," \" \"",[87,3259,2211],{"class":97},[87,3261,3262,3265,3268,3270,3272,3275,3278,3281,3283],{"class":89,"line":1445},[87,3263,3264],{"class":111},"    if",[87,3266,3267],{"class":97}," ((",[87,3269,1400],{"class":111},[87,3271,2217],{"class":97},[87,3273,3274],{"class":111},"%",[87,3276,3277],{"class":97}," a.cols) ",[87,3279,3280],{"class":111},"==",[87,3282,1389],{"class":231},[87,3284,3010],{"class":97},[87,3286,3287],{"class":89,"line":1451},[87,3288,1448],{"class":97},[87,3290,3291,3293,3295],{"class":89,"line":1477},[87,3292,3083],{"class":97},[87,3294,1214],{"class":111},[87,3296,3097],{"class":97},[87,3298,3299],{"class":89,"line":1483},[87,3300,1480],{"class":97},[87,3302,3303],{"class":89,"line":2214},[87,3304,1486],{"class":97},[10,3306,3307,3308,3311,3312,3315,3316,3319,3320,3322],{},"The iterator variable type for the Mat class is ",[22,3309,3310],{},"cv::MatIterator_\u003C>",", and when defining it, you also need to declare the data type inside the angle brackets. The start of the Mat class iterator is ",[22,3313,3314],{},"Mat.begin\u003C>()",", and the end is ",[22,3317,3318],{},"Mat.end\u003C>()",", which works the same as other iterators. The pointer position moves forward using the ",[22,3321,1400],{}," operator, and data is read by first reading every channel of the first element, then every channel of the second element, and so on, until the last channel of the last element.",[10,3324,3325],{},[496,3326,3327],{},"4. Accessing elements via matrix element address positioning",[10,3329,3330],{},"The first three methods of reading elements all require knowing the data type stored in the Mat matrix. Additionally, from a conceptual standpoint, we prefer to read data within a specific channel by declaring \"row X, column X, channel X.\" The method for reading data in this way is provided in Code Listing 2-23.",[10,3332,3333],{},"Code Listing 2-23 Accessing elements via address positioning of matrix elements",[78,3335,3337],{"className":80,"code":3336,"language":82,"meta":83,"style":83},"(int)(*(b.data + b.step[0] * row + b.step[1] * col + channel));\n",[22,3338,3339],{"__ignoreMap":83},[87,3340,3341,3343,3345,3347,3349,3352,3354,3357,3359,3361,3363,3366,3368,3370,3372,3374,3376,3379,3381],{"class":89,"line":90},[87,3342,124],{"class":97},[87,3344,28],{"class":111},[87,3346,3247],{"class":97},[87,3348,1853],{"class":111},[87,3350,3351],{"class":97},"(b.data ",[87,3353,1471],{"class":111},[87,3355,3356],{"class":97}," b.step[",[87,3358,1042],{"class":231},[87,3360,1718],{"class":97},[87,3362,1853],{"class":111},[87,3364,3365],{"class":97}," row ",[87,3367,1471],{"class":111},[87,3369,3356],{"class":97},[87,3371,1562],{"class":231},[87,3373,1718],{"class":97},[87,3375,1853],{"class":111},[87,3377,3378],{"class":97}," col ",[87,3380,1471],{"class":111},[87,3382,3383],{"class":97}," channel));\n",[10,3385,3386,3387,3390,3391,3394,3395,3398],{},"In the code, the variable ",[22,3388,3389],{},"row"," represents the row index of a data element, ",[22,3392,3393],{},"col"," represents the column index, and ",[22,3396,3397],{},"channel"," represents the channel index. This approach is similar to reading data through pointers, where the address pointer of the first data element is shifted by a certain number of positions to point to the desired data. However, this method allows direct reading by specifying the row, column, and channel numbers, eliminating the need for the user to calculate the position of a data element within the row's data storage space.",[14,3400,3402],{"id":3401},"reading-and-displaying-images","Reading and Displaying Images",[10,3404,3405],{},"This section will provide a detailed introduction to the functions related to image reading and display.",[42,3407,3409,3410],{"id":3408},"the-image-reading-function-imread","The image reading function ",[22,3411,121],{},[10,3413,3414,3415,3418],{},"We have already introduced the calling method of the image reading function ",[22,3416,3417],{},"imread()"," earlier (see Code Listing 1-1). Here we provide the function prototype (see Code Listing 2-24).\nCode Listing 2-24 Prototype of the imread() function",[78,3420,3422],{"className":80,"code":3421,"language":82,"meta":83,"style":83},"cv::Mat cv::imread(const String &filename,\n                   int flags = IMREAD_COLOR);\n",[22,3423,3424,3455],{"__ignoreMap":83},[87,3425,3426,3428,3430,3432,3434,3436,3438,3440,3442,3445,3448,3452],{"class":89,"line":90},[87,3427,94],{"class":93},[87,3429,118],{"class":97},[87,3431,32],{"class":93},[87,3433,115],{"class":93},[87,3435,118],{"class":97},[87,3437,121],{"class":93},[87,3439,124],{"class":97},[87,3441,731],{"class":111},[87,3443,3444],{"class":93}," String",[87,3446,3447],{"class":111}," &",[87,3449,3451],{"class":3450},"s4XuR","filename",[87,3453,3454],{"class":97},",\n",[87,3456,3457,3460,3463,3466],{"class":89,"line":105},[87,3458,3459],{"class":111},"                   int",[87,3461,3462],{"class":3450}," flags",[87,3464,3465],{"class":111}," =",[87,3467,3468],{"class":97}," IMREAD_COLOR);\n",[566,3470,3471,3474],{},[569,3472,3473],{},"filename: The name of the image file to read, including the image path, name, and file extension.",[569,3475,3476],{},"flags: Flags for reading images, such as reading a color image as a grayscale image. The default parameter reads the image in color format. Optional parameters are listed in Table 2-3.",[10,3478,3479,3480,3483,3484,3487,3488,3490,3491,3493],{},"The function is used to read a specified image and return it as a Mat class variable. If the image file does not exist, is corrupted, or is in an unsupported format, the image cannot be read, and the function returns an empty matrix. Therefore, you can check whether the image was successfully read by verifying if the ",[22,3481,3482],{},"data"," attribute of the returned matrix is empty or if the ",[22,3485,3486],{},"empty()"," function returns true. If reading the image fails, the ",[22,3489,3482],{}," attribute returns 0, and the ",[22,3492,3486],{}," function returns 1.",[10,3495,3496],{},"The function can read image files in multiple formats. However, due to differences in codecs across operating systems, an image file that can be read on one system may not be readable on another. BMP and DIB files are always readable regardless of the system. On Windows and macOS, OpenCV uses its built-in codecs (libjpeg, libpng, libtiff, and libjasper) by default, so it can read JPEG (jpg, jpeg, jpe), PNG, and TIFF (tiff, tif) files. On Linux systems, these codecs need to be installed manually; once installed, the same file types can be read.",[10,3498,3499],{},"However, it should be noted that whether this function can read file data is unrelated to the file extension. Instead, it determines the image type based on the file's content. For example, if a file's extension is changed from .png to .exe, the function can still read the image. However, if the extension is changed from .exe to .png, the function will not be able to load the file.\nThe first parameter of this function provides the address of the image to be read as a string, and the second parameter sets the mode for reading the image. The default mode reads the image in color. Depending on different requirements, this parameter can be changed. OpenCV 4.1 offers 13 modes for reading images, which can be summarized as reading in the original format, reading as a grayscale image, reading as a color image, reading with multiple bits, and reading while scaling the image to a certain size. The specific selectable parameters and their functions are shown in Table 2-3. It should be noted that converting a color image to grayscale through internal codec conversion may produce results that differ from converting a color image to grayscale within an OpenCV program. These flag parameters can be declared simultaneously as long as their functions do not conflict, with different parameters separated by \"|\"separated by.",[10,3501,3502],{},"Table 2-3 Parameters for reading image formats in the imread() function",[253,3504,3505,3517],{},[256,3506,3507],{},[259,3508,3509,3512,3515],{},[262,3510,3511],{"align":2459},"Flag parameters",[262,3513,3514],{"align":2459},"Quick note",[262,3516,2463],{"align":2459},[272,3518,3519,3530,3540,3550,3560,3570,3580,3591,3602],{},[259,3520,3521,3524,3527],{},[277,3522,3523],{"align":2459},"IMREAD_UNCHANGED",[277,3525,3526],{"align":2459},"-1",[277,3528,3529],{"align":2459},"Read the image as-is, preserving the alpha channel (4th channel).",[259,3531,3532,3535,3537],{},[277,3533,3534],{"align":2459},"IMREAD_GRAYSCALE",[277,3536,1042],{"align":2459},[277,3538,3539],{"align":2459},"After converting the image to a single-channel grayscale image, read it.",[259,3541,3542,3545,3547],{},[277,3543,3544],{"align":2459},"IMREAD_COLOR",[277,3546,1562],{"align":2459},[277,3548,3549],{"align":2459},"Convert the image to a 3-channel BGR color image.",[259,3551,3552,3555,3557],{},[277,3553,3554],{"align":2459},"IMREAD_ANYDEPTH",[277,3556,871],{"align":2459},[277,3558,3559],{"align":2459},"Preserve the original image's 16-bit and 32-bit depth; if this parameter is not specified, it will be converted to 8-bit for reading.",[259,3561,3562,3565,3567],{},[277,3563,3564],{"align":2459},"IMREAD_ANYCOLOR",[277,3566,1230],{"align":2459},[277,3568,3569],{"align":2459},"Read the image in any possible color.",[259,3571,3572,3575,3577],{},[277,3573,3574],{"align":2459},"IMREAD_LOAD_GDAL",[277,3576,1249],{"align":2459},[277,3578,3579],{"align":2459},"Load the image using the GDAL driver.",[259,3581,3582,3585,3588],{},[277,3583,3584],{"align":2459},"IMREAD_REDUCED_GRAYSCALE_2",[277,3586,3587],{"align":2459},"16",[277,3589,3590],{"align":2459},"Convert the image to a single-channel grayscale image and reduce its size by half. You can change the last digit to 4 to reduce it by 1/4, or to 8 to reduce it by 1/8.",[259,3592,3593,3596,3599],{},[277,3594,3595],{"align":2459},"IMREAD_REDUCED_COLOR_2",[277,3597,3598],{"align":2459},"17",[277,3600,3601],{"align":2459},"Convert the image to a 3-channel color image, and reduce its size by half. You can change the last digit to achieve a reduction to 1/4 (change the last digit to 4) or 1/8 (change the last digit to 8).",[259,3603,3604,3607,3610],{},[277,3605,3606],{"align":2459},"IMREAD_IGNORE_ORIENTATION",[277,3608,3609],{"align":2459},"128",[277,3611,3612],{"align":2459},"Do not rotate the image based on EXIF orientation.",[10,3614,3615,3616,3619],{},"Note: By default, the number of pixels in a read image must be less than 2³⁰. This requirement does not affect most image processing fields, but satellite remote sensing images and ultra-high-resolution images may exceed this threshold. You can adjust the maximum number of readable pixels by modifying the ",[22,3617,3618],{},"OPENCV_IO_MAX_IMAGE_PIXELS"," parameter in the system variables.",[42,3621,3623],{"id":3622},"image-window-function-namedwindow","Image window function namedWindow",[10,3625,3626],{},"In our previous programs, we did not introduce window functions because when displaying an image without explicitly defining an image window, the program automatically generates a window for display. However, sometimes it is necessary to perform operations on the image window before displaying the image, such as adding a slider. In such cases, the image window needs to be created in advance. Code Listing 2-25 provides the prototype for the window creation function.\nCode Listing 2-25 Prototype of the namedWindow() function",[78,3628,3630],{"className":80,"code":3629,"language":82,"meta":83,"style":83},"void cv::namedWindow(const String &winname,\n                     int flags = WINDOW_AUTOSIZE);\n",[22,3631,3632,3657],{"__ignoreMap":83},[87,3633,3634,3637,3639,3641,3644,3646,3648,3650,3652,3655],{"class":89,"line":90},[87,3635,3636],{"class":111},"void",[87,3638,115],{"class":93},[87,3640,118],{"class":97},[87,3642,3643],{"class":93},"namedWindow",[87,3645,124],{"class":97},[87,3647,731],{"class":111},[87,3649,3444],{"class":93},[87,3651,3447],{"class":111},[87,3653,3654],{"class":3450},"winname",[87,3656,3454],{"class":97},[87,3658,3659,3662,3664,3666],{"class":89,"line":105},[87,3660,3661],{"class":111},"                     int",[87,3663,3462],{"class":3450},[87,3665,3465],{"class":111},[87,3667,3668],{"class":97}," WINDOW_AUTOSIZE);\n",[566,3670,3671,3674],{},[569,3672,3673],{},"winname: Window name, used as the window identifier.",[569,3675,3676],{},"flags: Window property setting flags.",[10,3678,3679,3680,170,3683,3686],{},"This function creates a window variable used to display images and trackbars. The window is referenced by its name. If a window with the same name already exists when this function is called, the function does nothing. Creating a window consumes some memory resources, so after creating a window with this function, it is necessary to close the window when it is no longer needed to free up memory resources. OpenCV provides two functions for closing windows: ",[22,3681,3682],{},"cv::destroyWindow()",[22,3684,3685],{},"cv::destroyAllWindows()",". As their names suggest, the first function is used to close a window with a specific name — simply pass the window name as a string inside the parentheses to close that window. The second function closes all windows in the program and is typically used at the end of the program.",[10,3688,3689],{},"However, in a simple program, we don't actually need to call these functions, because all application resources and windows are automatically closed when the program exits. Although not actively releasing windows will still free window resources when the program ends, OpenCV version 4.0 will report an error about unreleased windows upon termination, while OpenCV version 4.1 will not.",[10,3691,3692],{},"The first parameter of this function declares the name of the window, used for unique window identification. The second parameter declares the window's properties, mainly used to set whether the window size is adjustable and whether the displayed image fills the window. The specific selectable parameters and their meanings are given in Table 2-4. By default, the function's loaded flag parameter is WINDOW_AUTOSIZE.|WINDOW_KEEPRATIO|WINDOW_GUI_EXPANDED。",[10,3694,3695],{},"Table 2-4 namedWindow() function window property flag parameters",[253,3697,3698,3708],{},[256,3699,3700],{},[259,3701,3702,3704,3706],{},[262,3703,3511],{"align":2459},[262,3705,3514],{"align":2459},[262,3707,2463],{"align":2459},[272,3709,3710,3721,3732,3743,3753,3764,3774,3784],{},[259,3711,3712,3715,3718],{},[277,3713,3714],{"align":2459},"WINDOW_NORMAL",[277,3716,3717],{"align":2459},"0x00000000",[277,3719,3720],{"align":2459},"After displaying the image, allow the user to freely resize the window.",[259,3722,3723,3726,3729],{},[277,3724,3725],{"align":2459},"WINDOW_AUTOSIZE",[277,3727,3728],{"align":2459},"0x00000001",[277,3730,3731],{"align":2459},"Display the window according to the image size, and do not allow the user to resize it.",[259,3733,3734,3737,3740],{},[277,3735,3736],{"align":2459},"WINDOW_OPENGL",[277,3738,3739],{"align":2459},"0x00001000",[277,3741,3742],{"align":2459},"When creating a window, OpenGL will be supported.",[259,3744,3745,3748,3750],{},[277,3746,3747],{"align":2459},"WINDOW_FULLSCREEN",[277,3749,1562],{"align":2459},[277,3751,3752],{"align":2459},"Full-screen display window",[259,3754,3755,3758,3761],{},[277,3756,3757],{"align":2459},"WINDOW_FREERATIO",[277,3759,3760],{"align":2459},"0x00000100",[277,3762,3763],{"align":2459},"Resize the image to fill the window.",[259,3765,3766,3769,3771],{},[277,3767,3768],{"align":2459},"WINDOW_KEEPRATIO",[277,3770,3717],{"align":2459},[277,3772,3773],{"align":2459},"Maintain the image's aspect ratio.",[259,3775,3776,3779,3781],{},[277,3777,3778],{"align":2459},"WINDOW_GUI_EXPANDED",[277,3780,3717],{"align":2459},[277,3782,3783],{"align":2459},"The created window allows adding a toolbar and a status bar.",[259,3785,3786,3789,3792],{},[277,3787,3788],{"align":2459},"WINDOW_GUI_NORMAL",[277,3790,3791],{"align":2459},"0x00000010",[277,3793,3794],{"align":2459},"Create a window without a status bar and toolbar.",[42,3796,3798],{"id":3797},"image-display-function-imshow","Image display function imshow",[10,3800,3801,3802,3805],{},"We have already introduced how to call the image display function ",[22,3803,3804],{},"imshow()",". Here we provide the function prototype (see Code Listing 2-26).\nCode Listing 2-26 Prototype of the imshow() function",[78,3807,3809],{"className":80,"code":3808,"language":82,"meta":83,"style":83},"void cv::imshow(const String &winname,\n                InputArray mat);\n",[22,3810,3811,3834],{"__ignoreMap":83},[87,3812,3813,3815,3817,3819,3822,3824,3826,3828,3830,3832],{"class":89,"line":90},[87,3814,3636],{"class":111},[87,3816,115],{"class":93},[87,3818,118],{"class":97},[87,3820,3821],{"class":93},"imshow",[87,3823,124],{"class":97},[87,3825,731],{"class":111},[87,3827,3444],{"class":93},[87,3829,3447],{"class":111},[87,3831,3654],{"class":3450},[87,3833,3454],{"class":97},[87,3835,3836,3839,3842],{"class":89,"line":105},[87,3837,3838],{"class":93},"                InputArray",[87,3840,3841],{"class":3450}," mat",[87,3843,1257],{"class":97},[566,3845,3846,3849],{},[569,3847,3848],{},"winname: The name of the window to display the image, assigned as a string.",[569,3850,3851],{},"mat: The image matrix to be displayed.",[10,3853,3854,3855,3857],{},"This function displays an image in the specified window. If no image window with the same name has been created before this function is called, it creates a window with the ",[22,3856,3725],{}," flag, displaying the image at its original size. If an image window already exists, the image is scaled to fit the window's properties. The function scales the image based on its depth, following the specific scaling rules below:",[566,3859,3860,3863,3872],{},[569,3861,3862],{},"If the image is of an 8-bit unsigned type, it will be displayed as is.",[569,3864,3865,3866,163,3869,1159],{},"If the image is of 16-bit unsigned type or 32-bit integer type, the pixel values will be divided by 256, mapping the range from ",[87,3867,3868],{},"0, 255×256",[87,3870,3871],{},"0, 255",[569,3873,3874,3875,163,3878,1159],{},"If the image is of 32-bit or 64-bit floating-point type, multiply the pixels by 255 to map the range from ",[87,3876,3877],{},"0,1",[87,3879,3880],{},"0,255",[10,3882,3883],{},"The first parameter of the function is the name of the image display window, and the second parameter is the Mat class matrix of the image to be displayed. A special note here: the second parameter is not the common Mat class, but InputArray, which is a type declaration reference defined by OpenCV, used as an identifier for input parameters. When we encounter it, we can treat it as requiring a Mat class data input. Similarly, OpenCV also defines the OutputArray type for output, which we can also treat as outputting Mat class data.",[10,3885,3886,3887,3889,3890,3893,3894,3897,3898,3900],{},"After this function runs, the program continues executing subsequent code. If the subsequent code finishes and exits directly, the displayed image may flash and disappear instantly. Therefore, in programs that need to display images, the ",[22,3888,3804],{}," function is often followed by the ",[22,3891,3892],{},"cv::waitKey()"," function, which pauses the program for a period of time. The ",[22,3895,3896],{},"waitKey()"," function specifies a waiting duration in milliseconds. If the parameter is left as default or set to ",[22,3899,1042],{},", it means the function will wait until the user presses a key to end it.",[10,3902,3903],{},"Code to display an image:",[78,3905,3907],{"className":80,"code":3906,"language":82,"meta":83,"style":83},"#include \"chapter2_2_show_image/inc/show_image.hpp\"\n#include \u003Ciostream>\n#include \u003Copencv2/opencv.hpp>\n\n\nvoid opencv_function1(void)\n{\n    cv::Mat picture_demo_mat = cv::imread(std::string(MEDIA_PATH) + \"林星阑L.jpg\");\n    cv::imshow(\"xiaoshen\", picture_demo_mat);\n\n    std::cout \u003C\u003C \"成功运行OpenCV!\" \u003C\u003C std::endl; \n\n    cv::waitKey(0);             // 这句确保窗口一直打开\n}\n",[22,3908,3909,3917,3924,3931,3935,3939,3952,3956,3991,4007,4011,4034,4039,4058],{"__ignoreMap":83},[87,3910,3911,3914],{"class":89,"line":90},[87,3912,3913],{"class":111},"#include",[87,3915,3916],{"class":127}," \"chapter2_2_show_image/inc/show_image.hpp\"\n",[87,3918,3919,3921],{"class":89,"line":105},[87,3920,3913],{"class":111},[87,3922,3923],{"class":127}," \u003Ciostream>\n",[87,3925,3926,3928],{"class":89,"line":137},[87,3927,3913],{"class":111},[87,3929,3930],{"class":127}," \u003Copencv2/opencv.hpp>\n",[87,3932,3933],{"class":89,"line":431},[87,3934,399],{"emptyLinePlaceholder":398},[87,3936,3937],{"class":89,"line":436},[87,3938,399],{"emptyLinePlaceholder":398},[87,3940,3941,3943,3946,3948,3950],{"class":89,"line":1445},[87,3942,3636],{"class":111},[87,3944,3945],{"class":93}," opencv_function1",[87,3947,124],{"class":97},[87,3949,3636],{"class":111},[87,3951,3010],{"class":97},[87,3953,3954],{"class":89,"line":1451},[87,3955,1411],{"class":97},[87,3957,3958,3961,3964,3966,3968,3970,3972,3974,3977,3979,3981,3984,3986,3989],{"class":89,"line":1477},[87,3959,3960],{"class":93},"    cv",[87,3962,3963],{"class":97},"::Mat picture_demo_mat ",[87,3965,112],{"class":111},[87,3967,115],{"class":93},[87,3969,118],{"class":97},[87,3971,121],{"class":93},[87,3973,124],{"class":97},[87,3975,3976],{"class":93},"std",[87,3978,118],{"class":97},[87,3980,24],{"class":93},[87,3982,3983],{"class":97},"(MEDIA_PATH) ",[87,3985,1471],{"class":111},[87,3987,3988],{"class":127}," \"林星阑L.jpg\"",[87,3990,1257],{"class":97},[87,3992,3993,3995,3997,3999,4001,4004],{"class":89,"line":1483},[87,3994,3960],{"class":93},[87,3996,118],{"class":97},[87,3998,3821],{"class":93},[87,4000,124],{"class":97},[87,4002,4003],{"class":127},"\"xiaoshen\"",[87,4005,4006],{"class":97},", picture_demo_mat);\n",[87,4008,4009],{"class":89,"line":2214},[87,4010,399],{"emptyLinePlaceholder":398},[87,4012,4014,4017,4020,4022,4025,4028,4031],{"class":89,"line":4013},11,[87,4015,4016],{"class":93},"    std",[87,4018,4019],{"class":97},"::cout ",[87,4021,1214],{"class":111},[87,4023,4024],{"class":127}," \"成功运行OpenCV!\"",[87,4026,4027],{"class":111}," \u003C\u003C",[87,4029,4030],{"class":93}," std",[87,4032,4033],{"class":97},"::endl; \n",[87,4035,4037],{"class":89,"line":4036},12,[87,4038,399],{"emptyLinePlaceholder":398},[87,4040,4042,4044,4046,4049,4051,4053,4055],{"class":89,"line":4041},13,[87,4043,3960],{"class":93},[87,4045,118],{"class":97},[87,4047,4048],{"class":93},"waitKey",[87,4050,124],{"class":97},[87,4052,1042],{"class":231},[87,4054,131],{"class":97},[87,4056,4057],{"class":101},"             // 这句确保窗口一直打开\n",[87,4059,4061],{"class":89,"line":4060},14,[87,4062,1486],{"class":97},[10,4064,4065],{},"Code to display an image (using NVIDIA GPU CUDA acceleration):",[78,4067,4069],{"className":80,"code":4068,"language":82,"meta":83,"style":83},"#include \"chapter2_2_show_image/inc/show_image_CUDA.hpp\"\n#include \u003Ciostream>\n#include \u003Copencv2/opencv.hpp>\n\nvoid opencv_function2(void)\n{\n    cv::Mat picture_demo_mat = cv::imread(std::string(MEDIA_PATH) + \"林星阑H.jpg\");\n    cv::cuda::GpuMat gpuImage; \n    gpuImage.upload(picture_demo_mat); \n    cv::Mat result; \n    gpuImage.download(result);\n    cv::namedWindow(\"林星阑\",cv::WINDOW_NORMAL);\n    cv::imshow(\"林星阑\", result);\n    std::cout \u003C\u003C \"CUDA成功运行!\" \u003C\u003C std::endl;\n    cv::waitKey(0);             // 这句确保窗口一直打开\n\n}\n",[22,4070,4071,4078,4084,4090,4094,4107,4111,4142,4154,4165,4172,4182,4203,4218,4236,4253,4258],{"__ignoreMap":83},[87,4072,4073,4075],{"class":89,"line":90},[87,4074,3913],{"class":111},[87,4076,4077],{"class":127}," \"chapter2_2_show_image/inc/show_image_CUDA.hpp\"\n",[87,4079,4080,4082],{"class":89,"line":105},[87,4081,3913],{"class":111},[87,4083,3923],{"class":127},[87,4085,4086,4088],{"class":89,"line":137},[87,4087,3913],{"class":111},[87,4089,3930],{"class":127},[87,4091,4092],{"class":89,"line":431},[87,4093,399],{"emptyLinePlaceholder":398},[87,4095,4096,4098,4101,4103,4105],{"class":89,"line":436},[87,4097,3636],{"class":111},[87,4099,4100],{"class":93}," opencv_function2",[87,4102,124],{"class":97},[87,4104,3636],{"class":111},[87,4106,3010],{"class":97},[87,4108,4109],{"class":89,"line":1445},[87,4110,1411],{"class":97},[87,4112,4113,4115,4117,4119,4121,4123,4125,4127,4129,4131,4133,4135,4137,4140],{"class":89,"line":1451},[87,4114,3960],{"class":93},[87,4116,3963],{"class":97},[87,4118,112],{"class":111},[87,4120,115],{"class":93},[87,4122,118],{"class":97},[87,4124,121],{"class":93},[87,4126,124],{"class":97},[87,4128,3976],{"class":93},[87,4130,118],{"class":97},[87,4132,24],{"class":93},[87,4134,3983],{"class":97},[87,4136,1471],{"class":111},[87,4138,4139],{"class":127}," \"林星阑H.jpg\"",[87,4141,1257],{"class":97},[87,4143,4144,4146,4148,4151],{"class":89,"line":1477},[87,4145,3960],{"class":93},[87,4147,118],{"class":97},[87,4149,4150],{"class":93},"cuda",[87,4152,4153],{"class":97},"::GpuMat gpuImage; \n",[87,4155,4156,4159,4162],{"class":89,"line":1483},[87,4157,4158],{"class":97},"    gpuImage.",[87,4160,4161],{"class":93},"upload",[87,4163,4164],{"class":97},"(picture_demo_mat); \n",[87,4166,4167,4169],{"class":89,"line":2214},[87,4168,3960],{"class":93},[87,4170,4171],{"class":97},"::Mat result; \n",[87,4173,4174,4176,4179],{"class":89,"line":4013},[87,4175,4158],{"class":97},[87,4177,4178],{"class":93},"download",[87,4180,4181],{"class":97},"(result);\n",[87,4183,4184,4186,4188,4190,4192,4195,4198,4200],{"class":89,"line":4036},[87,4185,3960],{"class":93},[87,4187,118],{"class":97},[87,4189,3643],{"class":93},[87,4191,124],{"class":97},[87,4193,4194],{"class":127},"\"林星阑\"",[87,4196,4197],{"class":97},",",[87,4199,94],{"class":93},[87,4201,4202],{"class":97},"::WINDOW_NORMAL);\n",[87,4204,4205,4207,4209,4211,4213,4215],{"class":89,"line":4041},[87,4206,3960],{"class":93},[87,4208,118],{"class":97},[87,4210,3821],{"class":93},[87,4212,124],{"class":97},[87,4214,4194],{"class":127},[87,4216,4217],{"class":97},", result);\n",[87,4219,4220,4222,4224,4226,4229,4231,4233],{"class":89,"line":4060},[87,4221,4016],{"class":93},[87,4223,4019],{"class":97},[87,4225,1214],{"class":111},[87,4227,4228],{"class":127}," \"CUDA成功运行!\"",[87,4230,4027],{"class":111},[87,4232,4030],{"class":93},[87,4234,4235],{"class":97},"::endl;\n",[87,4237,4239,4241,4243,4245,4247,4249,4251],{"class":89,"line":4238},15,[87,4240,3960],{"class":93},[87,4242,118],{"class":97},[87,4244,4048],{"class":93},[87,4246,124],{"class":97},[87,4248,1042],{"class":231},[87,4250,131],{"class":97},[87,4252,4057],{"class":101},[87,4254,4256],{"class":89,"line":4255},16,[87,4257,399],{"emptyLinePlaceholder":398},[87,4259,4261],{"class":89,"line":4260},17,[87,4262,1486],{"class":97},[14,4264,4266],{"id":4265},"video-loading-and-camera-access","Video loading and camera access",[10,4268,4269],{},"Earlier, we introduced how to read image data through programs. This section will cover the VideoCapture class in OpenCV, which is designed for reading video files and accessing cameras.",[42,4271,4273],{"id":4272},"reading-video-data","Reading video data",[10,4275,4276,4277,4279,4280,4282,4283,4286],{},"Although a video file is composed of multiple images, the ",[22,4278,3417],{}," function cannot directly read video files. A dedicated video reading function is required to read the video and save each frame into a ",[22,4281,32],{}," class matrix. Code Listing 2-27 shows how to construct the ",[22,4284,4285],{},"VideoCapture"," class when reading a video file.\nCode Listing 2-27 VideoCapture Class Constructor for Reading Video Files",[78,4288,4290],{"className":80,"code":4289,"language":82,"meta":83,"style":83},"cv::VideoCapture::VideoCapture();  // 默认构造函数\n\ncv::VideoCapture::VideoCapture(const String& filename,\n                               int apiPreference = CAP_ANY);\n",[22,4291,4292,4310,4314,4337],{"__ignoreMap":83},[87,4293,4294,4296,4298,4300,4302,4304,4307],{"class":89,"line":90},[87,4295,94],{"class":93},[87,4297,118],{"class":97},[87,4299,4285],{"class":93},[87,4301,118],{"class":97},[87,4303,4285],{"class":93},[87,4305,4306],{"class":97},"();",[87,4308,4309],{"class":101},"  // 默认构造函数\n",[87,4311,4312],{"class":89,"line":105},[87,4313,399],{"emptyLinePlaceholder":398},[87,4315,4316,4318,4320,4322,4324,4326,4328,4330,4332,4334],{"class":89,"line":137},[87,4317,94],{"class":93},[87,4319,118],{"class":97},[87,4321,4285],{"class":93},[87,4323,118],{"class":97},[87,4325,4285],{"class":93},[87,4327,124],{"class":97},[87,4329,731],{"class":111},[87,4331,3444],{"class":97},[87,4333,737],{"class":111},[87,4335,4336],{"class":97}," filename,\n",[87,4338,4339,4342,4345,4347],{"class":89,"line":431},[87,4340,4341],{"class":111},"                               int",[87,4343,4344],{"class":97}," apiPreference ",[87,4346,112],{"class":111},[87,4348,4349],{"class":97}," CAP_ANY);\n",[566,4351,4352,4355],{},[569,4353,4354],{},"filename: The name of the video file or image sequence to read.",[569,4356,4357],{},"apiPreference: Properties set when reading data, such as encoding format, whether to call OpenNI, etc.",[10,4359,4360,4361,4364,4365,4368,4369,4372,4373,1159],{},"This function constructs a video stream capable of reading and processing video files. The first line in Code Listing 2-27 is the default constructor of the VideoCapture class, which simply declares a class capable of reading video data. The specific video file to be read needs to be specified at runtime using the ",[22,4362,4363],{},"open()"," function. For example, ",[22,4366,4367],{},"cap.open(\"1.avi\")"," instructs the VideoCapture class variable ",[22,4370,4371],{},"cap"," to read the video file ",[22,4374,4375],{},"1.avi",[10,4377,4378,4379,4381,4382,4384,4385,4387,4388,4391,4392,4394,4395,4397,4398,4400,4401,4403,4404,4406,4407,4409,4410,4412],{},"The second constructor declares the variable while also assigning the video data to it. The types of files that can be read include video files (e.g., video.avi), image sequences, or the URL of a video stream. When reading an image sequence, the image names must follow the format \"prefix + number,\" and are called using \"prefix + %02d.\" For example, if a folder contains images img_00.jpg, img_01.jpg, and img_02.jpg, the file name is specified as img_%02d.jpg when loading. The video reading property flag in the function defaults to automatically searching for an appropriate flag, so in everyday use, it can be left as default, and only the video name needs to be provided. Like the imread() function, the constructor may also fail to read the file, so it is necessary to check using the isOpened() function. If the read is successful, the return value is true; if it fails, the return value is false.\nThe constructor only loads the video file into a ",[22,4380,4285],{}," class variable. When we need to use the images from the video, we must export them from the ",[22,4383,4285],{}," variable into a ",[22,4386,32],{}," variable for subsequent data processing. This operation can be done using the ",[22,4389,4390],{},">>"," operator, which assigns images from the ",[22,4393,4285],{}," variable to the ",[22,4396,32],{}," variable in the order they appear in the video. Once all images in the ",[22,4399,4285],{}," variable have been assigned to the ",[22,4402,32],{}," variable, any further assignment will result in the ",[22,4405,32],{}," variable becoming an empty matrix. Therefore, the ",[22,4408,3486],{}," method can be used to check whether all images in the ",[22,4411,4285],{}," variable have been read.",[10,4414,2349,4415,4417,4418,4421,4422,4424,4425,4427],{},[22,4416,4285],{}," class also provides the ",[22,4419,4420],{},"get()"," function to view video properties by passing specific flags to retrieve attributes such as pixel dimensions, frame count, frame rate, and more. Commonly used flags and their meanings for the ",[22,4423,4420],{}," method in the ",[22,4426,4285],{}," class are listed in Table 2-5.",[10,4429,4430],{},"Table 2-5 Flag parameters in the get() method of the VideoCapture class",[253,4432,4433,4443],{},[256,4434,4435],{},[259,4436,4437,4439,4441],{},[262,4438,3511],{"align":2459},[262,4440,3514],{"align":2459},[262,4442,2463],{"align":2459},[272,4444,4445,4455,4465,4475,4485,4495,4505,4515,4526,4537,4548,4559],{},[259,4446,4447,4450,4452],{},[277,4448,4449],{"align":2459},"CAP_PROP_POS_MSEC",[277,4451,1042],{"align":2459},[277,4453,4454],{"align":2459},"The current position of the video file (in milliseconds)",[259,4456,4457,4460,4462],{},[277,4458,4459],{"align":2459},"CAP_PROP_FRAME_WIDTH",[277,4461,232],{"align":2459},[277,4463,4464],{"align":2459},"Width of the image in the video stream",[259,4466,4467,4470,4472],{},[277,4468,4469],{"align":2459},"CAP_PROP_FRAME_HEIGHT",[277,4471,1230],{"align":2459},[277,4473,4474],{"align":2459},"Height of the image in the video stream",[259,4476,4477,4480,4482],{},[277,4478,4479],{"align":2459},"CAP_PROP_FPS",[277,4481,876],{"align":2459},[277,4483,4484],{"align":2459},"Frame rate of images in a video stream (frames per second)",[259,4486,4487,4490,4492],{},[277,4488,4489],{"align":2459},"CAP_PROP_FOURCC",[277,4491,1239],{"align":2459},[277,4493,4494],{"align":2459},"4-character code for codec",[259,4496,4497,4500,4502],{},[277,4498,4499],{"align":2459},"CAP_PROP_FRAME_COUNT",[277,4501,1244],{"align":2459},[277,4503,4504],{"align":2459},"Number of frames in a video stream",[259,4506,4507,4510,4512],{},[277,4508,4509],{"align":2459},"CAP_PROP_FORMAT",[277,4511,1249],{"align":2459},[277,4513,4514],{"align":2459},"The format of the returned Mat object",[259,4516,4517,4520,4523],{},[277,4518,4519],{"align":2459},"CAP_PROP_BRIGHTNESS",[277,4521,4522],{"align":2459},"10",[277,4524,4525],{"align":2459},"Image brightness (only applicable to supported cameras)",[259,4527,4528,4531,4534],{},[277,4529,4530],{"align":2459},"CAP_PROP_CONTRAST",[277,4532,4533],{"align":2459},"11",[277,4535,4536],{"align":2459},"Image contrast (camera only)",[259,4538,4539,4542,4545],{},[277,4540,4541],{"align":2459},"CAP_PROP_SATURATION",[277,4543,4544],{"align":2459},"12",[277,4546,4547],{"align":2459},"Image saturation (camera only)",[259,4549,4550,4553,4556],{},[277,4551,4552],{"align":2459},"CAP_PROP_HUE",[277,4554,4555],{"align":2459},"13",[277,4557,4558],{"align":2459},"Image hue (camera only)",[259,4560,4561,4564,4567],{},[277,4562,4563],{"align":2459},"CAP_PROP_GAIN",[277,4565,4566],{"align":2459},"14",[277,4568,4569],{"align":2459},"Image gain (only applicable to supported cameras)",[10,4571,4572,4573,4575],{},"To become more familiar with the ",[22,4574,4285],{}," class, Code Listing 2-28 provides a program that reads a video, outputs its properties, and displays it at the original frame rate. The results are shown in Figure 2-6.",[10,4577,4578],{},"Code Listing 2-28 VideoCapture.cpp reads a video file.",[78,4580,4582],{"className":80,"code":4581,"language":82,"meta":83,"style":83},"#include \"chapter2_3_video_capture/inc/read_video.hpp\"\n#include \u003Ccstdio>\n#include \u003Copencv2/opencv.hpp>\n\n\nint opencv_function3(void)\n{\n    cv::VideoCapture video__(std::string(MEDIA_PATH) + \"hei.mp4\");\n    if(video__.isOpened() == true)  //判断视频是否导入成功\n    {\n        printf(\"视频中图像的宽度=%lf\",video__.get(cv::CAP_PROP_FRAME_WIDTH));\n        printf(\"视频中图像的高度=%lf\",video__.get(cv::CAP_PROP_FRAME_HEIGHT));\n        printf(\"视频的帧率=%lf\",video__.get(cv::CAP_PROP_FPS));\n        printf(\"视频的总帧数=%lf\",video__.get(cv::CAP_PROP_FRAME_COUNT));\n    }\n    else\n    {\n        printf(\"导入视频失败，请确认视频文件是否正确\");\n        return 1;\n    }\n\n    while(true)\n    {\n        cv::Mat frame__;\n        video__ >> frame__;\n        if(frame__.empty() == true) //检测图像是不是空的，如果是空的，说明视频最后一帧也已经导入完了\n        {\n        break;\n        }\n        cv::imshow(\"视频播放\",frame__);\n        cv::waitKey(1000 / video__.get(cv::CAP_PROP_FPS));   //FPS为1秒每帧（也就是帧的数量），用1000ms / 帧的数量 = 每帧所需时间\n    }\n    cv::waitKey(0);             // 这句确保窗口视频播放完后一直打开，不关闭\n}\n",[22,4583,4584,4591,4598,4604,4608,4612,4625,4629,4656,4679,4683,4712,4736,4760,4784,4788,4793,4797,4809,4819,4824,4829,4842,4847,4856,4867,4890,4896,4904,4910,4927,4959,4964,4982],{"__ignoreMap":83},[87,4585,4586,4588],{"class":89,"line":90},[87,4587,3913],{"class":111},[87,4589,4590],{"class":127}," \"chapter2_3_video_capture/inc/read_video.hpp\"\n",[87,4592,4593,4595],{"class":89,"line":105},[87,4594,3913],{"class":111},[87,4596,4597],{"class":127}," \u003Ccstdio>\n",[87,4599,4600,4602],{"class":89,"line":137},[87,4601,3913],{"class":111},[87,4603,3930],{"class":127},[87,4605,4606],{"class":89,"line":431},[87,4607,399],{"emptyLinePlaceholder":398},[87,4609,4610],{"class":89,"line":436},[87,4611,399],{"emptyLinePlaceholder":398},[87,4613,4614,4616,4619,4621,4623],{"class":89,"line":1445},[87,4615,28],{"class":111},[87,4617,4618],{"class":93}," opencv_function3",[87,4620,124],{"class":97},[87,4622,3636],{"class":111},[87,4624,3010],{"class":97},[87,4626,4627],{"class":89,"line":1451},[87,4628,1411],{"class":97},[87,4630,4631,4633,4636,4639,4641,4643,4645,4647,4649,4651,4654],{"class":89,"line":1477},[87,4632,3960],{"class":93},[87,4634,4635],{"class":97},"::VideoCapture ",[87,4637,4638],{"class":93},"video__",[87,4640,124],{"class":97},[87,4642,3976],{"class":93},[87,4644,118],{"class":97},[87,4646,24],{"class":93},[87,4648,3983],{"class":97},[87,4650,1471],{"class":111},[87,4652,4653],{"class":127}," \"hei.mp4\"",[87,4655,1257],{"class":97},[87,4657,4658,4660,4663,4666,4669,4671,4674,4676],{"class":89,"line":1483},[87,4659,3264],{"class":111},[87,4661,4662],{"class":97},"(video__.",[87,4664,4665],{"class":93},"isOpened",[87,4667,4668],{"class":97},"() ",[87,4670,3280],{"class":111},[87,4672,4673],{"class":231}," true",[87,4675,1403],{"class":97},[87,4677,4678],{"class":101},"  //判断视频是否导入成功\n",[87,4680,4681],{"class":89,"line":2214},[87,4682,1448],{"class":97},[87,4684,4685,4688,4690,4693,4696,4699,4702,4705,4707,4709],{"class":89,"line":4013},[87,4686,4687],{"class":93},"        printf",[87,4689,124],{"class":97},[87,4691,4692],{"class":127},"\"视频中图像的宽度=",[87,4694,4695],{"class":231},"%lf",[87,4697,4698],{"class":127},"\"",[87,4700,4701],{"class":97},",video__.",[87,4703,4704],{"class":93},"get",[87,4706,124],{"class":97},[87,4708,94],{"class":93},[87,4710,4711],{"class":97},"::CAP_PROP_FRAME_WIDTH));\n",[87,4713,4714,4716,4718,4721,4723,4725,4727,4729,4731,4733],{"class":89,"line":4036},[87,4715,4687],{"class":93},[87,4717,124],{"class":97},[87,4719,4720],{"class":127},"\"视频中图像的高度=",[87,4722,4695],{"class":231},[87,4724,4698],{"class":127},[87,4726,4701],{"class":97},[87,4728,4704],{"class":93},[87,4730,124],{"class":97},[87,4732,94],{"class":93},[87,4734,4735],{"class":97},"::CAP_PROP_FRAME_HEIGHT));\n",[87,4737,4738,4740,4742,4745,4747,4749,4751,4753,4755,4757],{"class":89,"line":4041},[87,4739,4687],{"class":93},[87,4741,124],{"class":97},[87,4743,4744],{"class":127},"\"视频的帧率=",[87,4746,4695],{"class":231},[87,4748,4698],{"class":127},[87,4750,4701],{"class":97},[87,4752,4704],{"class":93},[87,4754,124],{"class":97},[87,4756,94],{"class":93},[87,4758,4759],{"class":97},"::CAP_PROP_FPS));\n",[87,4761,4762,4764,4766,4769,4771,4773,4775,4777,4779,4781],{"class":89,"line":4060},[87,4763,4687],{"class":93},[87,4765,124],{"class":97},[87,4767,4768],{"class":127},"\"视频的总帧数=",[87,4770,4695],{"class":231},[87,4772,4698],{"class":127},[87,4774,4701],{"class":97},[87,4776,4704],{"class":93},[87,4778,124],{"class":97},[87,4780,94],{"class":93},[87,4782,4783],{"class":97},"::CAP_PROP_FRAME_COUNT));\n",[87,4785,4786],{"class":89,"line":4238},[87,4787,1480],{"class":97},[87,4789,4790],{"class":89,"line":4255},[87,4791,4792],{"class":111},"    else\n",[87,4794,4795],{"class":89,"line":4260},[87,4796,1448],{"class":97},[87,4798,4800,4802,4804,4807],{"class":89,"line":4799},18,[87,4801,4687],{"class":93},[87,4803,124],{"class":97},[87,4805,4806],{"class":127},"\"导入视频失败，请确认视频文件是否正确\"",[87,4808,1257],{"class":97},[87,4810,4812,4815,4817],{"class":89,"line":4811},19,[87,4813,4814],{"class":111},"        return",[87,4816,1217],{"class":231},[87,4818,2211],{"class":97},[87,4820,4822],{"class":89,"line":4821},20,[87,4823,1480],{"class":97},[87,4825,4827],{"class":89,"line":4826},21,[87,4828,399],{"emptyLinePlaceholder":398},[87,4830,4832,4835,4837,4840],{"class":89,"line":4831},22,[87,4833,4834],{"class":111},"    while",[87,4836,124],{"class":97},[87,4838,4839],{"class":231},"true",[87,4841,3010],{"class":97},[87,4843,4845],{"class":89,"line":4844},23,[87,4846,1448],{"class":97},[87,4848,4850,4853],{"class":89,"line":4849},24,[87,4851,4852],{"class":93},"        cv",[87,4854,4855],{"class":97},"::Mat frame__;\n",[87,4857,4859,4862,4864],{"class":89,"line":4858},25,[87,4860,4861],{"class":97},"        video__ ",[87,4863,4390],{"class":111},[87,4865,4866],{"class":97}," frame__;\n",[87,4868,4870,4873,4876,4879,4881,4883,4885,4887],{"class":89,"line":4869},26,[87,4871,4872],{"class":111},"        if",[87,4874,4875],{"class":97},"(frame__.",[87,4877,4878],{"class":93},"empty",[87,4880,4668],{"class":97},[87,4882,3280],{"class":111},[87,4884,4673],{"class":231},[87,4886,1403],{"class":97},[87,4888,4889],{"class":101}," //检测图像是不是空的，如果是空的，说明视频最后一帧也已经导入完了\n",[87,4891,4893],{"class":89,"line":4892},27,[87,4894,4895],{"class":97},"        {\n",[87,4897,4899,4902],{"class":89,"line":4898},28,[87,4900,4901],{"class":111},"        break",[87,4903,2211],{"class":97},[87,4905,4907],{"class":89,"line":4906},29,[87,4908,4909],{"class":97},"        }\n",[87,4911,4913,4915,4917,4919,4921,4924],{"class":89,"line":4912},30,[87,4914,4852],{"class":93},[87,4916,118],{"class":97},[87,4918,3821],{"class":93},[87,4920,124],{"class":97},[87,4922,4923],{"class":127},"\"视频播放\"",[87,4925,4926],{"class":97},",frame__);\n",[87,4928,4930,4932,4934,4936,4938,4941,4944,4947,4949,4951,4953,4956],{"class":89,"line":4929},31,[87,4931,4852],{"class":93},[87,4933,118],{"class":97},[87,4935,4048],{"class":93},[87,4937,124],{"class":97},[87,4939,4940],{"class":231},"1000",[87,4942,4943],{"class":111}," /",[87,4945,4946],{"class":97}," video__.",[87,4948,4704],{"class":93},[87,4950,124],{"class":97},[87,4952,94],{"class":93},[87,4954,4955],{"class":97},"::CAP_PROP_FPS));",[87,4957,4958],{"class":101},"   //FPS为1秒每帧（也就是帧的数量），用1000ms / 帧的数量 = 每帧所需时间\n",[87,4960,4962],{"class":89,"line":4961},32,[87,4963,1480],{"class":97},[87,4965,4967,4969,4971,4973,4975,4977,4979],{"class":89,"line":4966},33,[87,4968,3960],{"class":93},[87,4970,118],{"class":97},[87,4972,4048],{"class":93},[87,4974,124],{"class":97},[87,4976,1042],{"class":231},[87,4978,131],{"class":97},[87,4980,4981],{"class":101},"             // 这句确保窗口视频播放完后一直打开，不关闭\n",[87,4983,4985],{"class":89,"line":4984},34,[87,4986,1486],{"class":97},[10,4988,4989,4990],{},"Figure 2-6 Video reading program execution result\n",[37,4991],{"alt":39,"src":4992},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776174431344.webp",[42,4994,4996],{"id":4995},"direct-camera-call","Direct camera call",[10,4998,4999],{},"The VideoCapture class can also call the camera, with the construction method shown in Code Listing 2-29.",[10,5001,5002],{},"Code Listing 2-29 VideoCapture class calls the camera constructor",[78,5004,5006],{"className":80,"code":5005,"language":82,"meta":83,"style":83},"cv::VideoCapture::VideoCapture(int index,\n                               int apiPreference = CAP_ANY);\n",[22,5007,5008,5027],{"__ignoreMap":83},[87,5009,5010,5012,5014,5016,5018,5020,5022,5024],{"class":89,"line":90},[87,5011,94],{"class":93},[87,5013,118],{"class":97},[87,5015,4285],{"class":93},[87,5017,118],{"class":97},[87,5019,4285],{"class":93},[87,5021,124],{"class":97},[87,5023,28],{"class":111},[87,5025,5026],{"class":97}," index,\n",[87,5028,5029,5031,5033,5035],{"class":89,"line":105},[87,5030,4341],{"class":111},[87,5032,4344],{"class":97},[87,5034,112],{"class":111},[87,5036,4349],{"class":97},[10,5038,5039,5040,5042,5043,5045],{},"Comparing with Code Listing 2-27, the only difference between calling a camera and reading a video file is the first parameter. When calling a camera, the first parameter is the ID of the camera device to open, with IDs starting from 0. The method for reading image data from the camera is the same as reading from a video file — using the ",[22,5041,4390],{}," operator to capture the image captured by the camera at the current moment. Additionally, the attributes of the ",[22,5044,4285],{}," class used when reading video are also available. We changed the video file in Code Listing 2-28 to the camera ID (0) and ran the modified program from Code Listing 2-28 again. The result is shown in Figure 2-7.",[10,5047,5048],{},"Linux Query Camera ID:",[78,5050,5054],{"className":5051,"code":5052,"language":5053,"meta":83,"style":83},"language-bash shiki shiki-themes github-light github-dark","ls /dev/video*\n","bash",[22,5055,5056],{"__ignoreMap":83},[87,5057,5058,5061,5064],{"class":89,"line":90},[87,5059,5060],{"class":93},"ls",[87,5062,5063],{"class":127}," /dev/video",[87,5065,5066],{"class":231},"*\n",[10,5068,5069],{},"Then output",[78,5071,5073],{"className":5051,"code":5072,"language":5053,"meta":83,"style":83},"/dev/video0  /dev/video1  /dev/video2  /dev/video3\n",[22,5074,5075],{"__ignoreMap":83},[87,5076,5077,5080,5083,5086],{"class":89,"line":90},[87,5078,5079],{"class":93},"/dev/video0",[87,5081,5082],{"class":127},"  /dev/video1",[87,5084,5085],{"class":127},"  /dev/video2",[87,5087,5088],{"class":127},"  /dev/video3\n",[10,5090,5091],{},"The 4 camera devices here are not necessarily all real cameras. On my end, device 0 is the laptop's built-in camera, while device 2 is an external USB camera I connected. Just try each one.",[10,5093,5094,5095],{},"Figure 2-7 Result of running the camera program\n",[37,5096],{"alt":39,"src":5097},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776174483290.webp",[14,5099,5101],{"id":5100},"data-saving","Data saving",[10,5103,5104],{},"During image processing, new images are generated—for example, sharpening a blurry image through algorithms or converting a color image to grayscale. The processed results also need to be saved as image or video files. This section will detail how to save a Mat class matrix as an image or video file.",[42,5106,5108],{"id":5107},"saving-images","Saving images",[10,5110,5111,5112,5115],{},"OpenCV provides the ",[22,5113,5114],{},"imwrite()"," function for saving a Mat class matrix as an image file. The prototype of this function is given in Code Listing 2-30.",[10,5117,5118],{},"Code Listing 2-30 imwrite() function prototype",[78,5120,5122],{"className":80,"code":5121,"language":82,"meta":83,"style":83},"bool cv::imwrite(const String& filename,\n                 InputArray img,\n                 const std::vector\u003Cint>& params = std::vector\u003Cint>());\n",[22,5123,5124,5149,5159],{"__ignoreMap":83},[87,5125,5126,5129,5131,5133,5136,5138,5140,5142,5144,5147],{"class":89,"line":90},[87,5127,5128],{"class":111},"bool",[87,5130,115],{"class":93},[87,5132,118],{"class":97},[87,5134,5135],{"class":93},"imwrite",[87,5137,124],{"class":97},[87,5139,731],{"class":111},[87,5141,3444],{"class":93},[87,5143,737],{"class":111},[87,5145,5146],{"class":3450}," filename",[87,5148,3454],{"class":97},[87,5150,5151,5154,5157],{"class":89,"line":105},[87,5152,5153],{"class":93},"                 InputArray",[87,5155,5156],{"class":3450}," img",[87,5158,3454],{"class":97},[87,5160,5161,5164,5166,5168,5171,5173,5175,5177,5179,5182,5184,5186,5188,5190,5192,5194],{"class":89,"line":137},[87,5162,5163],{"class":111},"                 const",[87,5165,4030],{"class":93},[87,5167,118],{"class":97},[87,5169,5170],{"class":93},"vector",[87,5172,222],{"class":97},[87,5174,28],{"class":111},[87,5176,1461],{"class":97},[87,5178,737],{"class":111},[87,5180,5181],{"class":3450}," params",[87,5183,3465],{"class":111},[87,5185,4030],{"class":93},[87,5187,118],{"class":97},[87,5189,5170],{"class":93},[87,5191,222],{"class":97},[87,5193,28],{"class":111},[87,5195,5196],{"class":97},">());\n",[566,5198,5199,5202,5205,5208,5211,5214],{},[569,5200,5201],{},"filename: The address and filename for saving the image, including the image format.",[569,5203,5204],{},"img: The Mat class matrix variable to be saved.",[569,5206,5207],{},"params: Save image format attribute setting flag.\nThis function is used to save a Mat matrix as an image file. It returns true if the image is saved successfully, and false otherwise. For supported image formats, refer to the image file formats that the imread() function can read. Typically, this function can only save 8-bit single-channel images and 3-channel BGR color images, but you can save images in different formats by changing the third parameter. The bit depths that different image formats can support are as follows:",[569,5209,5210],{},"A 16-bit unsigned (CV_16U) image can be saved as PNG, JPEG, or TIFF format files.",[569,5212,5213],{},"32-bit floating-point (CV_32F) images can be saved as PFM, TIFF, OpenEXR, and Radiance HDR format files.",[569,5215,5216],{},"A 4-channel (Alpha channel) image can be saved as a PNG format file.\nIn general, the third parameter of this function does not need to be filled in. To save in a specified file format, simply change the file extension directly after the first parameter. However, when the data in the Mat matrix to be saved is special (e.g., 16-bit depth data), the third parameter needs to be set. The method for setting the third parameter is shown in Listing 2-31, and common optional flags are given in Table 2-6.",[10,5218,5219],{},"Code Listing 2-31 Setting the third parameter in the imwrite() function",[78,5221,5223],{"className":80,"code":5222,"language":82,"meta":83,"style":83},"vector\u003Cint> compression_params;\ncompression_params.push_back(IMWRITE_PNG_COMPRESSION);\ncompression_params.push_back(9);\nimwrite(filename, img, compression_params);\n",[22,5224,5225,5235,5246,5258],{"__ignoreMap":83},[87,5226,5227,5229,5232],{"class":89,"line":90},[87,5228,5170],{"class":97},[87,5230,5231],{"class":111},"\u003Cint>",[87,5233,5234],{"class":97}," compression_params;\n",[87,5236,5237,5240,5243],{"class":89,"line":105},[87,5238,5239],{"class":97},"compression_params.",[87,5241,5242],{"class":93},"push_back",[87,5244,5245],{"class":97},"(IMWRITE_PNG_COMPRESSION);\n",[87,5247,5248,5250,5252,5254,5256],{"class":89,"line":137},[87,5249,5239],{"class":97},[87,5251,5242],{"class":93},[87,5253,124],{"class":97},[87,5255,1254],{"class":231},[87,5257,1257],{"class":97},[87,5259,5260,5262],{"class":89,"line":431},[87,5261,5135],{"class":93},[87,5263,5264],{"class":97},"(filename, img, compression_params);\n",[10,5266,5267],{},"Table 2-6 Selectable flags and their effects for the third parameter of the imwrite() function",[253,5269,5270,5280],{},[256,5271,5272],{},[259,5273,5274,5276,5278],{},[262,5275,3511],{"align":2459},[262,5277,3514],{"align":2459},[262,5279,2463],{"align":2459},[272,5281,5282,5292,5302,5312,5322,5332,5342],{},[259,5283,5284,5287,5289],{},[277,5285,5286],{"align":2459},"IMWRITE_JPEG_QUALITY",[277,5288,1562],{"align":2459},[277,5290,5291],{"align":2459},"The image quality for files saved in JPEG format is graded from 0 to 100, with a default of 95.",[259,5293,5294,5297,5299],{},[277,5295,5296],{"align":2459},"IMWRITE_JPEG_PROGRESSIVE",[277,5298,871],{"align":2459},[277,5300,5301],{"align":2459},"Enable JPEG enhancement, set to 1; default value is 0 (False).",[259,5303,5304,5307,5309],{},[277,5305,5306],{"align":2459},"IMWRITE_JPEG_OPTIMIZE",[277,5308,232],{"align":2459},[277,5310,5311],{"align":2459},"Optimize JPEG format, enable set to 1, default parameter is 0 (False).",[259,5313,5314,5317,5319],{},[277,5315,5316],{"align":2459},"IMWRITE_JPEG_LUMA_QUALITY",[277,5318,876],{"align":2459},[277,5320,5321],{"align":2459},"JPEG format file's individual brightness quality level, ranging from 0 to 100, with a default of 0.",[259,5323,5324,5327,5329],{},[277,5325,5326],{"align":2459},"IMWRITE_JPEG_CHROMA_QUALITY",[277,5328,1239],{"align":2459},[277,5330,5331],{"align":2459},"Separate chroma quality level for JPEG format files, ranging from 0 to 100, default is 0.",[259,5333,5334,5337,5339],{},[277,5335,5336],{"align":2459},"IMWRITE_PNG_COMPRESSION",[277,5338,3587],{"align":2459},[277,5340,5341],{"align":2459},"Save as PNG format file compression level, 0–9. Higher values mean smaller file size and longer compression time. The default value is 1 (best speed setting).",[259,5343,5344,5347,5350],{},[277,5345,5346],{"align":2459},"IMWRITE_TIFF_COMPRESSION",[277,5348,5349],{"align":2459},"259",[277,5351,5352],{"align":2459},"Save as TIFF format file compression scheme",[10,5354,5355,5356,5358],{},"To better understand how to use the ",[22,5357,5114],{}," function, Code Listing 2-32 provides a program that generates a matrix with an Alpha channel and saves it as a PNG image. After running the program, a 4-channel PNG image is saved. To visualize the result more intuitively, Figure 2-8 shows the image as seen in the Image Watch plugin alongside the saved PNG image.",[10,5360,5361],{},"Code Listing 2-32 imgWriter.cpp Saving an Image",[78,5363,5365],{"className":80,"code":5364,"language":82,"meta":83,"style":83},"#include \"chapter2_4_save_media_file/inc/save_image.hpp\"\n#include \u003Ccstdio>\n#include \u003Copencv2/opencv.hpp>\n\n\nvoid AlphaMat(cv::Mat *mat);\n\nint opencv_function6(void)\n{\n    cv::Mat mat__(480,640,CV_8UC4);\n    AlphaMat(&mat__);\n    std::vector\u003Cint> compression_params;\n    compression_params.push_back(cv::IMWRITE_PNG_COMPRESSION);   //PNG图像压缩标志\n    compression_params.push_back(9);   //设置最高压缩质量\n    if(cv::imwrite(std::string(SRCSRC_PATH) + \"chapter2_4_save_media_file/save_files/save_image_test1.png\",mat__,compression_params) == false)\n    {\n        printf(\"保存成PNG图像失败\");\n        return 1;\n    }\n    printf(\"保存成PNG图像成功\");\n    return 0;\n}\n\nvoid AlphaMat(cv::Mat *mat)\n{\n  CV_Assert(mat->channels() == 4);  //如果通道不等于4，那么抛出异常\n  for(int i = 0;i \u003C mat->rows;i++)   //行\n  {\n    for(int j = 0;j \u003C mat->cols;j++)    //列\n    {\n      /*\n      cv::Vec4b bgra = mat->at\u003Ccv::Vec4b>(i,j);\n      bgra.val[0] = cv::saturate_cast\u003Cuint8_t>(255);    //B:255   //该函数防止溢出，里面的数只能是0-255\n      bgra.val[1] = cv::saturate_cast\u003Cuint8_t>(0);      //G:0\n      bgra.val[2] = cv::saturate_cast\u003Cuint8_t>(0);      //R:0\n      bgra.val[3] = cv::saturate_cast\u003Cuint8_t>(180);    //α:180\n      */\n      cv::Vec4b &bgra = mat->at\u003Ccv::Vec4b>(i,j);\n      bgra[0] = cv::saturate_cast\u003Cuint8_t>(255);     //B:255   //该函数防止溢出，里面的数只能是0-255\n      bgra[1] = cv::saturate_cast\u003Cuint8_t>(0);      //G:0   //重载运算符[]\n      bgra[2] = cv::saturate_cast\u003Cuint8_t>(0);      //R:0\n      bgra[3] = cv::saturate_cast\u003Cuint8_t>(90);     //α:90\n    }\n  }\n}\n",[22,5366,5367,5374,5380,5386,5390,5394,5416,5420,5433,5437,5458,5470,5481,5498,5513,5551,5555,5566,5574,5578,5590,5599,5603,5607,5627,5631,5653,5683,5688,5717,5721,5726,5731,5736,5741,5747,5753,5759,5790,5826,5859,5889,5920,5925,5931],{"__ignoreMap":83},[87,5368,5369,5371],{"class":89,"line":90},[87,5370,3913],{"class":111},[87,5372,5373],{"class":127}," \"chapter2_4_save_media_file/inc/save_image.hpp\"\n",[87,5375,5376,5378],{"class":89,"line":105},[87,5377,3913],{"class":111},[87,5379,4597],{"class":127},[87,5381,5382,5384],{"class":89,"line":137},[87,5383,3913],{"class":111},[87,5385,3930],{"class":127},[87,5387,5388],{"class":89,"line":431},[87,5389,399],{"emptyLinePlaceholder":398},[87,5391,5392],{"class":89,"line":436},[87,5393,399],{"emptyLinePlaceholder":398},[87,5395,5396,5398,5401,5403,5405,5407,5409,5411,5414],{"class":89,"line":1445},[87,5397,3636],{"class":111},[87,5399,5400],{"class":93}," AlphaMat",[87,5402,124],{"class":97},[87,5404,94],{"class":93},[87,5406,118],{"class":97},[87,5408,32],{"class":93},[87,5410,2190],{"class":111},[87,5412,5413],{"class":3450},"mat",[87,5415,1257],{"class":97},[87,5417,5418],{"class":89,"line":1451},[87,5419,399],{"emptyLinePlaceholder":398},[87,5421,5422,5424,5427,5429,5431],{"class":89,"line":1477},[87,5423,28],{"class":111},[87,5425,5426],{"class":93}," opencv_function6",[87,5428,124],{"class":97},[87,5430,3636],{"class":111},[87,5432,3010],{"class":97},[87,5434,5435],{"class":89,"line":1483},[87,5436,1411],{"class":97},[87,5438,5439,5441,5444,5447,5449,5451,5453,5455],{"class":89,"line":2214},[87,5440,3960],{"class":93},[87,5442,5443],{"class":97},"::Mat ",[87,5445,5446],{"class":93},"mat__",[87,5448,124],{"class":97},[87,5450,383],{"class":231},[87,5452,4197],{"class":97},[87,5454,378],{"class":231},[87,5456,5457],{"class":97},",CV_8UC4);\n",[87,5459,5460,5463,5465,5467],{"class":89,"line":4013},[87,5461,5462],{"class":93},"    AlphaMat",[87,5464,124],{"class":97},[87,5466,737],{"class":111},[87,5468,5469],{"class":97},"mat__);\n",[87,5471,5472,5474,5477,5479],{"class":89,"line":4036},[87,5473,4016],{"class":93},[87,5475,5476],{"class":97},"::vector",[87,5478,5231],{"class":111},[87,5480,5234],{"class":97},[87,5482,5483,5486,5488,5490,5492,5495],{"class":89,"line":4041},[87,5484,5485],{"class":97},"    compression_params.",[87,5487,5242],{"class":93},[87,5489,124],{"class":97},[87,5491,94],{"class":93},[87,5493,5494],{"class":97},"::IMWRITE_PNG_COMPRESSION);",[87,5496,5497],{"class":101},"   //PNG图像压缩标志\n",[87,5499,5500,5502,5504,5506,5508,5510],{"class":89,"line":4060},[87,5501,5485],{"class":97},[87,5503,5242],{"class":93},[87,5505,124],{"class":97},[87,5507,1254],{"class":231},[87,5509,131],{"class":97},[87,5511,5512],{"class":101},"   //设置最高压缩质量\n",[87,5514,5515,5517,5519,5521,5523,5525,5527,5529,5531,5533,5536,5538,5541,5544,5546,5549],{"class":89,"line":4238},[87,5516,3264],{"class":111},[87,5518,124],{"class":97},[87,5520,94],{"class":93},[87,5522,118],{"class":97},[87,5524,5135],{"class":93},[87,5526,124],{"class":97},[87,5528,3976],{"class":93},[87,5530,118],{"class":97},[87,5532,24],{"class":93},[87,5534,5535],{"class":97},"(SRCSRC_PATH) ",[87,5537,1471],{"class":111},[87,5539,5540],{"class":127}," \"chapter2_4_save_media_file/save_files/save_image_test1.png\"",[87,5542,5543],{"class":97},",mat__,compression_params) ",[87,5545,3280],{"class":111},[87,5547,5548],{"class":231}," false",[87,5550,3010],{"class":97},[87,5552,5553],{"class":89,"line":4255},[87,5554,1448],{"class":97},[87,5556,5557,5559,5561,5564],{"class":89,"line":4260},[87,5558,4687],{"class":93},[87,5560,124],{"class":97},[87,5562,5563],{"class":127},"\"保存成PNG图像失败\"",[87,5565,1257],{"class":97},[87,5567,5568,5570,5572],{"class":89,"line":4799},[87,5569,4814],{"class":111},[87,5571,1217],{"class":231},[87,5573,2211],{"class":97},[87,5575,5576],{"class":89,"line":4811},[87,5577,1480],{"class":97},[87,5579,5580,5583,5585,5588],{"class":89,"line":4821},[87,5581,5582],{"class":93},"    printf",[87,5584,124],{"class":97},[87,5586,5587],{"class":127},"\"保存成PNG图像成功\"",[87,5589,1257],{"class":97},[87,5591,5592,5595,5597],{"class":89,"line":4826},[87,5593,5594],{"class":111},"    return",[87,5596,1389],{"class":231},[87,5598,2211],{"class":97},[87,5600,5601],{"class":89,"line":4831},[87,5602,1486],{"class":97},[87,5604,5605],{"class":89,"line":4844},[87,5606,399],{"emptyLinePlaceholder":398},[87,5608,5609,5611,5613,5615,5617,5619,5621,5623,5625],{"class":89,"line":4849},[87,5610,3636],{"class":111},[87,5612,5400],{"class":93},[87,5614,124],{"class":97},[87,5616,94],{"class":93},[87,5618,118],{"class":97},[87,5620,32],{"class":93},[87,5622,2190],{"class":111},[87,5624,5413],{"class":3450},[87,5626,3010],{"class":97},[87,5628,5629],{"class":89,"line":4858},[87,5630,1411],{"class":97},[87,5632,5633,5636,5639,5641,5643,5645,5648,5650],{"class":89,"line":4869},[87,5634,5635],{"class":93},"  CV_Assert",[87,5637,5638],{"class":97},"(mat->",[87,5640,3067],{"class":93},[87,5642,4668],{"class":97},[87,5644,3280],{"class":111},[87,5646,5647],{"class":231}," 4",[87,5649,131],{"class":97},[87,5651,5652],{"class":101},"  //如果通道不等于4，那么抛出异常\n",[87,5654,5655,5658,5660,5662,5664,5666,5668,5671,5673,5676,5678,5680],{"class":89,"line":4892},[87,5656,5657],{"class":111},"  for",[87,5659,124],{"class":97},[87,5661,28],{"class":111},[87,5663,1384],{"class":97},[87,5665,112],{"class":111},[87,5667,1389],{"class":231},[87,5669,5670],{"class":97},";i ",[87,5672,222],{"class":111},[87,5674,5675],{"class":97}," mat->rows;i",[87,5677,1400],{"class":111},[87,5679,1403],{"class":97},[87,5681,5682],{"class":101},"   //行\n",[87,5684,5685],{"class":89,"line":4898},[87,5686,5687],{"class":97},"  {\n",[87,5689,5690,5692,5694,5696,5698,5700,5702,5705,5707,5710,5712,5714],{"class":89,"line":4906},[87,5691,1416],{"class":111},[87,5693,124],{"class":97},[87,5695,28],{"class":111},[87,5697,1423],{"class":97},[87,5699,112],{"class":111},[87,5701,1389],{"class":231},[87,5703,5704],{"class":97},";j ",[87,5706,222],{"class":111},[87,5708,5709],{"class":97}," mat->cols;j",[87,5711,1400],{"class":111},[87,5713,1403],{"class":97},[87,5715,5716],{"class":101},"    //列\n",[87,5718,5719],{"class":89,"line":4912},[87,5720,1448],{"class":97},[87,5722,5723],{"class":89,"line":4929},[87,5724,5725],{"class":101},"      /*\n",[87,5727,5728],{"class":89,"line":4961},[87,5729,5730],{"class":101},"      cv::Vec4b bgra = mat->at\u003Ccv::Vec4b>(i,j);\n",[87,5732,5733],{"class":89,"line":4966},[87,5734,5735],{"class":101},"      bgra.val[0] = cv::saturate_cast\u003Cuint8_t>(255);    //B:255   //该函数防止溢出，里面的数只能是0-255\n",[87,5737,5738],{"class":89,"line":4984},[87,5739,5740],{"class":101},"      bgra.val[1] = cv::saturate_cast\u003Cuint8_t>(0);      //G:0\n",[87,5742,5744],{"class":89,"line":5743},35,[87,5745,5746],{"class":101},"      bgra.val[2] = cv::saturate_cast\u003Cuint8_t>(0);      //R:0\n",[87,5748,5750],{"class":89,"line":5749},36,[87,5751,5752],{"class":101},"      bgra.val[3] = cv::saturate_cast\u003Cuint8_t>(180);    //α:180\n",[87,5754,5756],{"class":89,"line":5755},37,[87,5757,5758],{"class":101},"      */\n",[87,5760,5762,5765,5768,5770,5773,5775,5778,5780,5782,5785,5787],{"class":89,"line":5761},38,[87,5763,5764],{"class":93},"      cv",[87,5766,5767],{"class":97},"::Vec4b ",[87,5769,737],{"class":111},[87,5771,5772],{"class":97},"bgra ",[87,5774,112],{"class":111},[87,5776,5777],{"class":97}," mat->at",[87,5779,222],{"class":111},[87,5781,94],{"class":93},[87,5783,5784],{"class":97},"::Vec4b",[87,5786,1461],{"class":111},[87,5788,5789],{"class":97},"(i,j);\n",[87,5791,5793,5796,5798,5800,5802,5804,5806,5809,5811,5814,5816,5818,5820,5823],{"class":89,"line":5792},39,[87,5794,5795],{"class":97},"      bgra[",[87,5797,1042],{"class":231},[87,5799,1718],{"class":97},[87,5801,112],{"class":111},[87,5803,115],{"class":93},[87,5805,118],{"class":97},[87,5807,5808],{"class":93},"saturate_cast",[87,5810,222],{"class":97},[87,5812,5813],{"class":111},"uint8_t",[87,5815,228],{"class":97},[87,5817,1051],{"class":231},[87,5819,131],{"class":97},[87,5821,5822],{"class":101},"     //B:255",[87,5824,5825],{"class":101},"   //该函数防止溢出，里面的数只能是0-255\n",[87,5827,5829,5831,5833,5835,5837,5839,5841,5843,5845,5847,5849,5851,5853,5856],{"class":89,"line":5828},40,[87,5830,5795],{"class":97},[87,5832,1562],{"class":231},[87,5834,1718],{"class":97},[87,5836,112],{"class":111},[87,5838,115],{"class":93},[87,5840,118],{"class":97},[87,5842,5808],{"class":93},[87,5844,222],{"class":97},[87,5846,5813],{"class":111},[87,5848,228],{"class":97},[87,5850,1042],{"class":231},[87,5852,131],{"class":97},[87,5854,5855],{"class":101},"      //G:0",[87,5857,5858],{"class":101},"   //重载运算符[]\n",[87,5860,5862,5864,5866,5868,5870,5872,5874,5876,5878,5880,5882,5884,5886],{"class":89,"line":5861},41,[87,5863,5795],{"class":97},[87,5865,871],{"class":231},[87,5867,1718],{"class":97},[87,5869,112],{"class":111},[87,5871,115],{"class":93},[87,5873,118],{"class":97},[87,5875,5808],{"class":93},[87,5877,222],{"class":97},[87,5879,5813],{"class":111},[87,5881,228],{"class":97},[87,5883,1042],{"class":231},[87,5885,131],{"class":97},[87,5887,5888],{"class":101},"      //R:0\n",[87,5890,5892,5894,5896,5898,5900,5902,5904,5906,5908,5910,5912,5915,5917],{"class":89,"line":5891},42,[87,5893,5795],{"class":97},[87,5895,232],{"class":231},[87,5897,1718],{"class":97},[87,5899,112],{"class":111},[87,5901,115],{"class":93},[87,5903,118],{"class":97},[87,5905,5808],{"class":93},[87,5907,222],{"class":97},[87,5909,5813],{"class":111},[87,5911,228],{"class":97},[87,5913,5914],{"class":231},"90",[87,5916,131],{"class":97},[87,5918,5919],{"class":101},"     //α:90\n",[87,5921,5923],{"class":89,"line":5922},43,[87,5924,1480],{"class":97},[87,5926,5928],{"class":89,"line":5927},44,[87,5929,5930],{"class":97},"  }\n",[87,5932,5934],{"class":89,"line":5933},45,[87,5935,1486],{"class":97},[10,5937,5938,5939],{},"Figure 2-8 The 4-channel image in the program and after saving (left: Image Watch, right: PNG file)\n",[37,5940],{"alt":39,"src":5941},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776174513642.webp",[42,5943,5945],{"id":5944},"saving-the-video","Saving the video",[10,5947,5948],{},"Sometimes we need to generate a video from multiple images, or directly save camera-captured data as a video file. OpenCV provides the VideoWriter class for saving multiple images into a video file. The prototype of this class's constructor is given in Code Listing 2-33.",[10,5950,5951],{},"Listing 2-33: VideoWriter Class Constructor for Saving Video Files",[78,5953,5955],{"className":80,"code":5954,"language":82,"meta":83,"style":83},"cv::VideoWriter::VideoWriter();  // 默认构造函数\n\ncv::VideoWriter::VideoWriter(const String& filename,\n                             int fourcc,\n                             double fps,\n                             Size frameSize,\n                             bool isColor = true);\n",[22,5956,5957,5974,5978,6000,6008,6016,6021],{"__ignoreMap":83},[87,5958,5959,5961,5963,5966,5968,5970,5972],{"class":89,"line":90},[87,5960,94],{"class":93},[87,5962,118],{"class":97},[87,5964,5965],{"class":93},"VideoWriter",[87,5967,118],{"class":97},[87,5969,5965],{"class":93},[87,5971,4306],{"class":97},[87,5973,4309],{"class":101},[87,5975,5976],{"class":89,"line":105},[87,5977,399],{"emptyLinePlaceholder":398},[87,5979,5980,5982,5984,5986,5988,5990,5992,5994,5996,5998],{"class":89,"line":137},[87,5981,94],{"class":93},[87,5983,118],{"class":97},[87,5985,5965],{"class":93},[87,5987,118],{"class":97},[87,5989,5965],{"class":93},[87,5991,124],{"class":97},[87,5993,731],{"class":111},[87,5995,3444],{"class":97},[87,5997,737],{"class":111},[87,5999,4336],{"class":97},[87,6001,6002,6005],{"class":89,"line":431},[87,6003,6004],{"class":111},"                             int",[87,6006,6007],{"class":97}," fourcc,\n",[87,6009,6010,6013],{"class":89,"line":436},[87,6011,6012],{"class":111},"                             double",[87,6014,6015],{"class":97}," fps,\n",[87,6017,6018],{"class":89,"line":1445},[87,6019,6020],{"class":97},"                             Size frameSize,\n",[87,6022,6023,6026,6029,6031,6033],{"class":89,"line":1451},[87,6024,6025],{"class":111},"                             bool",[87,6027,6028],{"class":97}," isColor ",[87,6030,112],{"class":111},[87,6032,4673],{"class":231},[87,6034,1257],{"class":97},[566,6036,6037,6040,6043,6046,6049],{},[569,6038,6039],{},"filename: The address and filename for saving the video, including the video format.",[569,6041,6042],{},"fourcc: A 4-character codec code for compressing frames, with detailed parameters provided in Table 2-7.",[569,6044,6045],{},"fps: The frame rate at which the video is saved, meaning the number of images per second in the video.",[569,6047,6048],{},"frameSize: The dimensions of the video frame.",[569,6050,6051],{},"isColor: Whether the saved video is a color video.",[10,6053,6054,6055,6058,6059,6061,6062,6065],{},"The first line of default constructor usage in Code Listing 2-33 is the same as ",[22,6056,6057],{},"VideoCapture()",": both create a data stream for saving video. Later, the ",[22,6060,4363],{}," function is used to set parameters such as the save file name, codec, and frame count. The second constructor requires the first input parameter to be the name of the video file to save, and the second parameter is the codec identifier. The available codec options are listed in Table 2-7. If the value ",[22,6063,6064],{},"\"-1\""," is assigned, it will automatically search for a suitable codec. Note that the input method differs slightly between OpenCV 4.0 and OpenCV 4.1, with the specific differences given in Table 2-7. The third parameter is the frame rate for saving the video, which can be set freely based on requirements—for example, to achieve double-speed playback or slow-motion playback of the original video. The fourth parameter sets the size of the saved video file. It is important to ensure that this size matches the image dimensions; otherwise, the video cannot be saved. The last parameter sets whether the saved video is in color. By default, the program saves the video as a color video.",[10,6067,6068,6069,6071,6072,6075,6076,6078,6079,6081,6082,6085,6086,1159],{},"This function is very similar to ",[22,6070,6057],{},". Both can use the ",[22,6073,6074],{},"isOpened()"," function to check whether a video stream was successfully created, and ",[22,6077,4420],{}," to view various properties of the video stream. When saving a video, you simply assign each generated frame to the video stream one by one using the ",[22,6080,1214],{}," operator (or the ",[22,6083,6084],{},"write()"," function), and finally close the video stream with ",[22,6087,6088],{},"release()",[10,6090,6091],{},"Table 2-7 Video encoding formats",[253,6093,6094,6106],{},[256,6095,6096],{},[259,6097,6098,6101,6104],{},[262,6099,6100],{"align":2459},"OpenCV 4.1 version logo",[262,6102,6103],{"align":2459},"OpenCV 4.0 version logo",[262,6105,2463],{"align":2459},[272,6107,6108,6123,6138,6153,6168,6183,6198,6213],{},[259,6109,6110,6115,6120],{},[277,6111,6112],{"align":2459},[22,6113,6114],{},"VideoWriter::fourcc('D', 'I', 'V', 'X')",[277,6116,6117],{"align":2459},[22,6118,6119],{},"CV_FOURCC('D', 'I', 'V', 'X')",[277,6121,6122],{"align":2459},"MPEG-4 encoding",[259,6124,6125,6130,6135],{},[277,6126,6127],{"align":2459},[22,6128,6129],{},"VideoWriter::fourcc('P', 'I', 'M', '1')",[277,6131,6132],{"align":2459},[22,6133,6134],{},"CV_FOURCC('P', 'I', 'M', '1')",[277,6136,6137],{"align":2459},"MPEG-1 encoding",[259,6139,6140,6145,6150],{},[277,6141,6142],{"align":2459},[22,6143,6144],{},"VideoWriter::fourcc('M', 'J', 'P', 'G')",[277,6146,6147],{"align":2459},[22,6148,6149],{},"CV_FOURCC('M', 'J', 'P', 'G')",[277,6151,6152],{"align":2459},"JPEG encoding (average performance)",[259,6154,6155,6160,6165],{},[277,6156,6157],{"align":2459},[22,6158,6159],{},"VideoWriter::fourcc('M', 'P', '4', '2')",[277,6161,6162],{"align":2459},[22,6163,6164],{},"CV_FOURCC('M', 'P', '4', '2')",[277,6166,6167],{"align":2459},"MPEG-4.2 encoding",[259,6169,6170,6175,6180],{},[277,6171,6172],{"align":2459},[22,6173,6174],{},"VideoWriter::fourcc('D', 'I', 'V', '3')",[277,6176,6177],{"align":2459},[22,6178,6179],{},"CV_FOURCC('D', 'I', 'V', '3')",[277,6181,6182],{"align":2459},"MPEG-4.3 encoding",[259,6184,6185,6190,6195],{},[277,6186,6187],{"align":2459},[22,6188,6189],{},"VideoWriter::fourcc('U', '2', '6', '3')",[277,6191,6192],{"align":2459},[22,6193,6194],{},"CV_FOURCC('U', '2', '6', '3')",[277,6196,6197],{"align":2459},"H.263 encoding",[259,6199,6200,6205,6210],{},[277,6201,6202],{"align":2459},[22,6203,6204],{},"VideoWriter::fourcc('I', '2', '6', '3')",[277,6206,6207],{"align":2459},[22,6208,6209],{},"CV_FOURCC('I', '2', '6', '3')",[277,6211,6212],{"align":2459},"H263I encoding",[259,6214,6215,6220,6225],{},[277,6216,6217],{"align":2459},[22,6218,6219],{},"VideoWriter::fourcc('F', 'L', 'V', '1')",[277,6221,6222],{"align":2459},[22,6223,6224],{},"CV_FOURCC('F', 'L', 'V', '1')",[277,6226,6227],{"align":2459},"FLV1 encoding",[10,6229,6230],{},"To better understand how to use the VideoWriter() class, Code Listing 2-34 provides an example of generating a new video file using existing video file data or directly from a camera feed. Readers should focus on understanding the similarities between the VideoWriter() and VideoCapture() classes, as well as important considerations when using them.",[10,6232,6233],{},"Code Listing 2-34 VideoWriter.cpp saves a video file",[78,6235,6237],{"className":80,"code":6236,"language":82,"meta":83,"style":83},"#include \"chapter2_4_save_media_file/inc/save_video.hpp\"\n#include \u003Ccstdio>\n#include \u003Copencv2/opencv.hpp>\n\n\ntemplate \u003Ctypename T>\nbool Save_Video(T file_opened_name_or_index,const std::string & file_saved_name);\n\nint opencv_function5(void)\n{\n    // 截取视频里的一段视频并保存到本地\n    Save_Video\u003Cconst std::string &>(std::string(MEDIA_PATH) + \"hei.mp4\",std::string(SRCSRC_PATH) + \"chapter2_4_save_media_file/save_files/save_video_test1.mp4\");\n\n    // 截取摄像头里的一段视频并保存到本地\n    // Save_Video\u003Cint>(2,std::string(SRCSRC_PATH) + \"chapter2_4_save_media_file/save_files/save_video_test2.mp4\");\n    \n    return 0;\n}\n\n\ntemplate \u003Ctypename T>\nbool Save_Video(T file_opened_name_or_index,const std::string & file_saved_name)\n{\n    cv::Mat img;\n    cv::VideoCapture video(file_opened_name_or_index);\n    if(video.isOpened() == true)\n    {\n        printf(\"调用摄像头或打开视频成功!\");\n        printf(\"视频中图像的宽度=%lf\",video.get(cv::CAP_PROP_FRAME_WIDTH));\n        printf(\"视频中图像的高度=%lf\",video.get(cv::CAP_PROP_FRAME_HEIGHT));\n        printf(\"视频的帧率=%lf\",video.get(cv::CAP_PROP_FPS));\n        printf(\"视频的总帧数=%lf\",video.get(cv::CAP_PROP_FRAME_COUNT));\n    }\n    else\n    {\n        printf(\"调用摄像头或者视频失败，请检查摄像头是否连接成功或者视频文件是否存在\");\n        return false;\n    }\n    video >> img;\n    if(img.empty() == true)\n    {\n        printf(\"帧图像获取失败!\");\n        return false;\n    }\n    cv::VideoWriter writer;\n    auto file_name = file_saved_name;\n    int codec = writer.fourcc('M','J','P','G');\n    double fps = 30.0;\n    auto size = img.size();\n    bool isColor = (img.type() == CV_8UC3);\n    writer.open(file_name,codec,fps,size,isColor);\n\n    if(writer.isOpened() == true)  //判断视频流是否创建成功!\n    {\n        printf(\"视频流创建成功!\");\n    }\n    else\n    {\n        printf(\"视频流创建失败，请确认是否为合法输入!\");\n        return false;\n    }\n\n    while(true)\n    {\n        if(video.read(img) == false)   //判断是否还能够继续从摄像头或者视频中读出一帧图像\n        {\n            printf(\"摄像头断开连接或者视频读取完成!\");\n            break;\n        }\n        writer \u003C\u003C img;  //writer.write(img);\n        cv::namedWindow(\"Live\");\n        cv::imshow(\"Live\",img);\n        int8_t keyborad_value = cv::waitKey(1000 / video.get(cv::CAP_PROP_FPS));   //FPS为1秒每帧（也就是帧的数量），用1000ms / 帧的数量 = 每帧所需时间\n        if(keyborad_value == 27)  //ESC键的ASCII码值为27，按下ESC键退出循环\n        {\n            break;\n        }\n    }\n    video.release();\n    writer.release();\n    return true;\n}\n",[22,6238,6239,6246,6252,6258,6262,6266,6283,6315,6319,6332,6336,6341,6389,6393,6398,6403,6408,6416,6420,6424,6428,6440,6468,6472,6479,6491,6508,6512,6523,6546,6568,6590,6612,6616,6620,6624,6635,6643,6647,6657,6674,6678,6689,6697,6701,6708,6722,6761,6777,6794,6817,6829,6834,6855,6860,6872,6877,6882,6887,6899,6908,6913,6918,6929,6934,6956,6961,6974,6982,6987,7001,7017,7033,7069,7087,7092,7099,7104,7109,7120,7129,7138],{"__ignoreMap":83},[87,6240,6241,6243],{"class":89,"line":90},[87,6242,3913],{"class":111},[87,6244,6245],{"class":127}," \"chapter2_4_save_media_file/inc/save_video.hpp\"\n",[87,6247,6248,6250],{"class":89,"line":105},[87,6249,3913],{"class":111},[87,6251,4597],{"class":127},[87,6253,6254,6256],{"class":89,"line":137},[87,6255,3913],{"class":111},[87,6257,3930],{"class":127},[87,6259,6260],{"class":89,"line":431},[87,6261,399],{"emptyLinePlaceholder":398},[87,6263,6264],{"class":89,"line":436},[87,6265,399],{"emptyLinePlaceholder":398},[87,6267,6268,6271,6274,6277,6280],{"class":89,"line":1445},[87,6269,6270],{"class":111},"template",[87,6272,6273],{"class":97}," \u003C",[87,6275,6276],{"class":111},"typename",[87,6278,6279],{"class":93}," T",[87,6281,6282],{"class":97},">\n",[87,6284,6285,6287,6290,6292,6295,6298,6300,6302,6304,6306,6308,6310,6313],{"class":89,"line":1451},[87,6286,5128],{"class":111},[87,6288,6289],{"class":93}," Save_Video",[87,6291,124],{"class":97},[87,6293,6294],{"class":93},"T",[87,6296,6297],{"class":3450}," file_opened_name_or_index",[87,6299,4197],{"class":97},[87,6301,731],{"class":111},[87,6303,4030],{"class":93},[87,6305,118],{"class":97},[87,6307,24],{"class":93},[87,6309,3447],{"class":111},[87,6311,6312],{"class":3450}," file_saved_name",[87,6314,1257],{"class":97},[87,6316,6317],{"class":89,"line":1477},[87,6318,399],{"emptyLinePlaceholder":398},[87,6320,6321,6323,6326,6328,6330],{"class":89,"line":1483},[87,6322,28],{"class":111},[87,6324,6325],{"class":93}," opencv_function5",[87,6327,124],{"class":97},[87,6329,3636],{"class":111},[87,6331,3010],{"class":97},[87,6333,6334],{"class":89,"line":2214},[87,6335,1411],{"class":97},[87,6337,6338],{"class":89,"line":4013},[87,6339,6340],{"class":101},"    // 截取视频里的一段视频并保存到本地\n",[87,6342,6343,6346,6348,6350,6352,6354,6356,6358,6360,6362,6364,6366,6368,6370,6372,6374,6376,6378,6380,6382,6384,6387],{"class":89,"line":4036},[87,6344,6345],{"class":93},"    Save_Video",[87,6347,222],{"class":97},[87,6349,731],{"class":111},[87,6351,4030],{"class":93},[87,6353,118],{"class":97},[87,6355,24],{"class":93},[87,6357,3447],{"class":111},[87,6359,228],{"class":97},[87,6361,3976],{"class":93},[87,6363,118],{"class":97},[87,6365,24],{"class":93},[87,6367,3983],{"class":97},[87,6369,1471],{"class":111},[87,6371,4653],{"class":127},[87,6373,4197],{"class":97},[87,6375,3976],{"class":93},[87,6377,118],{"class":97},[87,6379,24],{"class":93},[87,6381,5535],{"class":97},[87,6383,1471],{"class":111},[87,6385,6386],{"class":127}," \"chapter2_4_save_media_file/save_files/save_video_test1.mp4\"",[87,6388,1257],{"class":97},[87,6390,6391],{"class":89,"line":4041},[87,6392,399],{"emptyLinePlaceholder":398},[87,6394,6395],{"class":89,"line":4060},[87,6396,6397],{"class":101},"    // 截取摄像头里的一段视频并保存到本地\n",[87,6399,6400],{"class":89,"line":4238},[87,6401,6402],{"class":101},"    // Save_Video\u003Cint>(2,std::string(SRCSRC_PATH) + \"chapter2_4_save_media_file/save_files/save_video_test2.mp4\");\n",[87,6404,6405],{"class":89,"line":4255},[87,6406,6407],{"class":97},"    \n",[87,6409,6410,6412,6414],{"class":89,"line":4260},[87,6411,5594],{"class":111},[87,6413,1389],{"class":231},[87,6415,2211],{"class":97},[87,6417,6418],{"class":89,"line":4799},[87,6419,1486],{"class":97},[87,6421,6422],{"class":89,"line":4811},[87,6423,399],{"emptyLinePlaceholder":398},[87,6425,6426],{"class":89,"line":4821},[87,6427,399],{"emptyLinePlaceholder":398},[87,6429,6430,6432,6434,6436,6438],{"class":89,"line":4826},[87,6431,6270],{"class":111},[87,6433,6273],{"class":97},[87,6435,6276],{"class":111},[87,6437,6279],{"class":93},[87,6439,6282],{"class":97},[87,6441,6442,6444,6446,6448,6450,6452,6454,6456,6458,6460,6462,6464,6466],{"class":89,"line":4831},[87,6443,5128],{"class":111},[87,6445,6289],{"class":93},[87,6447,124],{"class":97},[87,6449,6294],{"class":93},[87,6451,6297],{"class":3450},[87,6453,4197],{"class":97},[87,6455,731],{"class":111},[87,6457,4030],{"class":93},[87,6459,118],{"class":97},[87,6461,24],{"class":93},[87,6463,3447],{"class":111},[87,6465,6312],{"class":3450},[87,6467,3010],{"class":97},[87,6469,6470],{"class":89,"line":4844},[87,6471,1411],{"class":97},[87,6473,6474,6476],{"class":89,"line":4849},[87,6475,3960],{"class":93},[87,6477,6478],{"class":97},"::Mat img;\n",[87,6480,6481,6483,6485,6488],{"class":89,"line":4858},[87,6482,3960],{"class":93},[87,6484,4635],{"class":97},[87,6486,6487],{"class":93},"video",[87,6489,6490],{"class":97},"(file_opened_name_or_index);\n",[87,6492,6493,6495,6498,6500,6502,6504,6506],{"class":89,"line":4869},[87,6494,3264],{"class":111},[87,6496,6497],{"class":97},"(video.",[87,6499,4665],{"class":93},[87,6501,4668],{"class":97},[87,6503,3280],{"class":111},[87,6505,4673],{"class":231},[87,6507,3010],{"class":97},[87,6509,6510],{"class":89,"line":4892},[87,6511,1448],{"class":97},[87,6513,6514,6516,6518,6521],{"class":89,"line":4898},[87,6515,4687],{"class":93},[87,6517,124],{"class":97},[87,6519,6520],{"class":127},"\"调用摄像头或打开视频成功!\"",[87,6522,1257],{"class":97},[87,6524,6525,6527,6529,6531,6533,6535,6538,6540,6542,6544],{"class":89,"line":4906},[87,6526,4687],{"class":93},[87,6528,124],{"class":97},[87,6530,4692],{"class":127},[87,6532,4695],{"class":231},[87,6534,4698],{"class":127},[87,6536,6537],{"class":97},",video.",[87,6539,4704],{"class":93},[87,6541,124],{"class":97},[87,6543,94],{"class":93},[87,6545,4711],{"class":97},[87,6547,6548,6550,6552,6554,6556,6558,6560,6562,6564,6566],{"class":89,"line":4912},[87,6549,4687],{"class":93},[87,6551,124],{"class":97},[87,6553,4720],{"class":127},[87,6555,4695],{"class":231},[87,6557,4698],{"class":127},[87,6559,6537],{"class":97},[87,6561,4704],{"class":93},[87,6563,124],{"class":97},[87,6565,94],{"class":93},[87,6567,4735],{"class":97},[87,6569,6570,6572,6574,6576,6578,6580,6582,6584,6586,6588],{"class":89,"line":4929},[87,6571,4687],{"class":93},[87,6573,124],{"class":97},[87,6575,4744],{"class":127},[87,6577,4695],{"class":231},[87,6579,4698],{"class":127},[87,6581,6537],{"class":97},[87,6583,4704],{"class":93},[87,6585,124],{"class":97},[87,6587,94],{"class":93},[87,6589,4759],{"class":97},[87,6591,6592,6594,6596,6598,6600,6602,6604,6606,6608,6610],{"class":89,"line":4961},[87,6593,4687],{"class":93},[87,6595,124],{"class":97},[87,6597,4768],{"class":127},[87,6599,4695],{"class":231},[87,6601,4698],{"class":127},[87,6603,6537],{"class":97},[87,6605,4704],{"class":93},[87,6607,124],{"class":97},[87,6609,94],{"class":93},[87,6611,4783],{"class":97},[87,6613,6614],{"class":89,"line":4966},[87,6615,1480],{"class":97},[87,6617,6618],{"class":89,"line":4984},[87,6619,4792],{"class":111},[87,6621,6622],{"class":89,"line":5743},[87,6623,1448],{"class":97},[87,6625,6626,6628,6630,6633],{"class":89,"line":5749},[87,6627,4687],{"class":93},[87,6629,124],{"class":97},[87,6631,6632],{"class":127},"\"调用摄像头或者视频失败，请检查摄像头是否连接成功或者视频文件是否存在\"",[87,6634,1257],{"class":97},[87,6636,6637,6639,6641],{"class":89,"line":5755},[87,6638,4814],{"class":111},[87,6640,5548],{"class":231},[87,6642,2211],{"class":97},[87,6644,6645],{"class":89,"line":5761},[87,6646,1480],{"class":97},[87,6648,6649,6652,6654],{"class":89,"line":5792},[87,6650,6651],{"class":97},"    video ",[87,6653,4390],{"class":111},[87,6655,6656],{"class":97}," img;\n",[87,6658,6659,6661,6664,6666,6668,6670,6672],{"class":89,"line":5828},[87,6660,3264],{"class":111},[87,6662,6663],{"class":97},"(img.",[87,6665,4878],{"class":93},[87,6667,4668],{"class":97},[87,6669,3280],{"class":111},[87,6671,4673],{"class":231},[87,6673,3010],{"class":97},[87,6675,6676],{"class":89,"line":5861},[87,6677,1448],{"class":97},[87,6679,6680,6682,6684,6687],{"class":89,"line":5891},[87,6681,4687],{"class":93},[87,6683,124],{"class":97},[87,6685,6686],{"class":127},"\"帧图像获取失败!\"",[87,6688,1257],{"class":97},[87,6690,6691,6693,6695],{"class":89,"line":5922},[87,6692,4814],{"class":111},[87,6694,5548],{"class":231},[87,6696,2211],{"class":97},[87,6698,6699],{"class":89,"line":5927},[87,6700,1480],{"class":97},[87,6702,6703,6705],{"class":89,"line":5933},[87,6704,3960],{"class":93},[87,6706,6707],{"class":97},"::VideoWriter writer;\n",[87,6709,6711,6714,6717,6719],{"class":89,"line":6710},46,[87,6712,6713],{"class":111},"    auto",[87,6715,6716],{"class":97}," file_name ",[87,6718,112],{"class":111},[87,6720,6721],{"class":97}," file_saved_name;\n",[87,6723,6725,6728,6731,6733,6736,6739,6741,6744,6746,6749,6751,6754,6756,6759],{"class":89,"line":6724},47,[87,6726,6727],{"class":111},"    int",[87,6729,6730],{"class":97}," codec ",[87,6732,112],{"class":111},[87,6734,6735],{"class":97}," writer.",[87,6737,6738],{"class":93},"fourcc",[87,6740,124],{"class":97},[87,6742,6743],{"class":127},"'M'",[87,6745,4197],{"class":97},[87,6747,6748],{"class":127},"'J'",[87,6750,4197],{"class":97},[87,6752,6753],{"class":127},"'P'",[87,6755,4197],{"class":97},[87,6757,6758],{"class":127},"'G'",[87,6760,1257],{"class":97},[87,6762,6764,6767,6770,6772,6775],{"class":89,"line":6763},48,[87,6765,6766],{"class":111},"    double",[87,6768,6769],{"class":97}," fps ",[87,6771,112],{"class":111},[87,6773,6774],{"class":231}," 30.0",[87,6776,2211],{"class":97},[87,6778,6780,6782,6785,6787,6790,6792],{"class":89,"line":6779},49,[87,6781,6713],{"class":111},[87,6783,6784],{"class":97}," size ",[87,6786,112],{"class":111},[87,6788,6789],{"class":97}," img.",[87,6791,606],{"class":93},[87,6793,519],{"class":97},[87,6795,6797,6800,6802,6804,6807,6810,6812,6814],{"class":89,"line":6796},50,[87,6798,6799],{"class":111},"    bool",[87,6801,6028],{"class":97},[87,6803,112],{"class":111},[87,6805,6806],{"class":97}," (img.",[87,6808,6809],{"class":93},"type",[87,6811,4668],{"class":97},[87,6813,3280],{"class":111},[87,6815,6816],{"class":97}," CV_8UC3);\n",[87,6818,6820,6823,6826],{"class":89,"line":6819},51,[87,6821,6822],{"class":97},"    writer.",[87,6824,6825],{"class":93},"open",[87,6827,6828],{"class":97},"(file_name,codec,fps,size,isColor);\n",[87,6830,6832],{"class":89,"line":6831},52,[87,6833,399],{"emptyLinePlaceholder":398},[87,6835,6837,6839,6842,6844,6846,6848,6850,6852],{"class":89,"line":6836},53,[87,6838,3264],{"class":111},[87,6840,6841],{"class":97},"(writer.",[87,6843,4665],{"class":93},[87,6845,4668],{"class":97},[87,6847,3280],{"class":111},[87,6849,4673],{"class":231},[87,6851,1403],{"class":97},[87,6853,6854],{"class":101},"  //判断视频流是否创建成功!\n",[87,6856,6858],{"class":89,"line":6857},54,[87,6859,1448],{"class":97},[87,6861,6863,6865,6867,6870],{"class":89,"line":6862},55,[87,6864,4687],{"class":93},[87,6866,124],{"class":97},[87,6868,6869],{"class":127},"\"视频流创建成功!\"",[87,6871,1257],{"class":97},[87,6873,6875],{"class":89,"line":6874},56,[87,6876,1480],{"class":97},[87,6878,6880],{"class":89,"line":6879},57,[87,6881,4792],{"class":111},[87,6883,6885],{"class":89,"line":6884},58,[87,6886,1448],{"class":97},[87,6888,6890,6892,6894,6897],{"class":89,"line":6889},59,[87,6891,4687],{"class":93},[87,6893,124],{"class":97},[87,6895,6896],{"class":127},"\"视频流创建失败，请确认是否为合法输入!\"",[87,6898,1257],{"class":97},[87,6900,6902,6904,6906],{"class":89,"line":6901},60,[87,6903,4814],{"class":111},[87,6905,5548],{"class":231},[87,6907,2211],{"class":97},[87,6909,6911],{"class":89,"line":6910},61,[87,6912,1480],{"class":97},[87,6914,6916],{"class":89,"line":6915},62,[87,6917,399],{"emptyLinePlaceholder":398},[87,6919,6921,6923,6925,6927],{"class":89,"line":6920},63,[87,6922,4834],{"class":111},[87,6924,124],{"class":97},[87,6926,4839],{"class":231},[87,6928,3010],{"class":97},[87,6930,6932],{"class":89,"line":6931},64,[87,6933,1448],{"class":97},[87,6935,6937,6939,6941,6944,6947,6949,6951,6953],{"class":89,"line":6936},65,[87,6938,4872],{"class":111},[87,6940,6497],{"class":97},[87,6942,6943],{"class":93},"read",[87,6945,6946],{"class":97},"(img) ",[87,6948,3280],{"class":111},[87,6950,5548],{"class":231},[87,6952,1403],{"class":97},[87,6954,6955],{"class":101},"   //判断是否还能够继续从摄像头或者视频中读出一帧图像\n",[87,6957,6959],{"class":89,"line":6958},66,[87,6960,4895],{"class":97},[87,6962,6964,6967,6969,6972],{"class":89,"line":6963},67,[87,6965,6966],{"class":93},"            printf",[87,6968,124],{"class":97},[87,6970,6971],{"class":127},"\"摄像头断开连接或者视频读取完成!\"",[87,6973,1257],{"class":97},[87,6975,6977,6980],{"class":89,"line":6976},68,[87,6978,6979],{"class":111},"            break",[87,6981,2211],{"class":97},[87,6983,6985],{"class":89,"line":6984},69,[87,6986,4909],{"class":97},[87,6988,6990,6993,6995,6998],{"class":89,"line":6989},70,[87,6991,6992],{"class":97},"        writer ",[87,6994,1214],{"class":111},[87,6996,6997],{"class":97}," img;",[87,6999,7000],{"class":101},"  //writer.write(img);\n",[87,7002,7004,7006,7008,7010,7012,7015],{"class":89,"line":7003},71,[87,7005,4852],{"class":93},[87,7007,118],{"class":97},[87,7009,3643],{"class":93},[87,7011,124],{"class":97},[87,7013,7014],{"class":127},"\"Live\"",[87,7016,1257],{"class":97},[87,7018,7020,7022,7024,7026,7028,7030],{"class":89,"line":7019},72,[87,7021,4852],{"class":93},[87,7023,118],{"class":97},[87,7025,3821],{"class":93},[87,7027,124],{"class":97},[87,7029,7014],{"class":127},[87,7031,7032],{"class":97},",img);\n",[87,7034,7036,7039,7042,7044,7046,7048,7050,7052,7054,7056,7059,7061,7063,7065,7067],{"class":89,"line":7035},73,[87,7037,7038],{"class":111},"        int8_t",[87,7040,7041],{"class":97}," keyborad_value ",[87,7043,112],{"class":111},[87,7045,115],{"class":93},[87,7047,118],{"class":97},[87,7049,4048],{"class":93},[87,7051,124],{"class":97},[87,7053,4940],{"class":231},[87,7055,4943],{"class":111},[87,7057,7058],{"class":97}," video.",[87,7060,4704],{"class":93},[87,7062,124],{"class":97},[87,7064,94],{"class":93},[87,7066,4955],{"class":97},[87,7068,4958],{"class":101},[87,7070,7072,7074,7077,7079,7082,7084],{"class":89,"line":7071},74,[87,7073,4872],{"class":111},[87,7075,7076],{"class":97},"(keyborad_value ",[87,7078,3280],{"class":111},[87,7080,7081],{"class":231}," 27",[87,7083,1403],{"class":97},[87,7085,7086],{"class":101},"  //ESC键的ASCII码值为27，按下ESC键退出循环\n",[87,7088,7090],{"class":89,"line":7089},75,[87,7091,4895],{"class":97},[87,7093,7095,7097],{"class":89,"line":7094},76,[87,7096,6979],{"class":111},[87,7098,2211],{"class":97},[87,7100,7102],{"class":89,"line":7101},77,[87,7103,4909],{"class":97},[87,7105,7107],{"class":89,"line":7106},78,[87,7108,1480],{"class":97},[87,7110,7112,7115,7118],{"class":89,"line":7111},79,[87,7113,7114],{"class":97},"    video.",[87,7116,7117],{"class":93},"release",[87,7119,519],{"class":97},[87,7121,7123,7125,7127],{"class":89,"line":7122},80,[87,7124,6822],{"class":97},[87,7126,7117],{"class":93},[87,7128,519],{"class":97},[87,7130,7132,7134,7136],{"class":89,"line":7131},81,[87,7133,5594],{"class":111},[87,7135,4673],{"class":231},[87,7137,2211],{"class":97},[87,7139,7141],{"class":89,"line":7140},82,[87,7142,1486],{"class":97},[10,7144,7145],{},"Save images from a video.",[78,7147,7149],{"className":80,"code":7148,"language":82,"meta":83,"style":83},"#include \"chapter2_4_save_media_file/inc/save_image_in_video.hpp\"\n#include \u003Ccstdio>\n#include \u003Copencv2/opencv.hpp>\n\n\nint opencv_function7(void)\n{\n    cv::VideoCapture video__(0);\n    cv::Mat frame__;\n    if(video__.isOpened() == true)  //判断视频是否导入成功\n    {\n        printf(\"视频中图像的宽度=%lf\",video__.get(cv::CAP_PROP_FRAME_WIDTH));\n        printf(\"视频中图像的高度=%lf\",video__.get(cv::CAP_PROP_FRAME_HEIGHT));\n        printf(\"视频的帧率=%lf\",video__.get(cv::CAP_PROP_FPS));\n        printf(\"视频的总帧数=%lf\",video__.get(cv::CAP_PROP_FRAME_COUNT));\n    }\n    else\n    {\n        printf(\"导入摄像头视频失败，请确认摄像头是否正常打开\");\n        return 1;\n    }\n    printf(\"按下空格键截图!\");\n    printf(\"按下ESC结束播放!\");\n    while(true)\n    {\n        video__ >> frame__;\n        cv::imshow(\"Live\",frame__);\n        int32_t key_boards_val = cv::waitKey(1000/video__.get(cv::CAP_PROP_FPS));\n        if(key_boards_val==32)   //检测到按下了空格键\n        {\n            if(cv::imwrite(std::string(SRCSRC_PATH) + \"chapter2_4_save_media_file/save_files/save_image_test2.png\",frame__) == false)\n            {\n                printf(\"截图失败!\");\n            }\n            else\n            {\n                printf(\"截图成功!\");\n            }\n            if(frame__.empty() == true) //检测图像是不是空的，如果是空的，说明视频最后一帧也已经导入完了\n            {\n                printf(\"视频播放结束,请选择截图或是按ESC退出!\");\n            }\n        }\n        else if(key_boards_val==27)   //检测到按下了ESC按键\n        {\n            break;\n        }\n    }\n    video__.release();\n    printf(\"播放被终止或已结束!\");\n\n    return 0;\n}\n",[22,7150,7151,7158,7164,7170,7174,7178,7191,7195,7209,7215,7233,7237,7259,7281,7303,7325,7329,7333,7337,7348,7356,7360,7371,7382,7392,7396,7404,7418,7451,7468,7472,7509,7514,7526,7531,7536,7540,7551,7555,7573,7577,7588,7592,7596,7616,7620,7626,7630,7634,7643,7654,7658,7666],{"__ignoreMap":83},[87,7152,7153,7155],{"class":89,"line":90},[87,7154,3913],{"class":111},[87,7156,7157],{"class":127}," \"chapter2_4_save_media_file/inc/save_image_in_video.hpp\"\n",[87,7159,7160,7162],{"class":89,"line":105},[87,7161,3913],{"class":111},[87,7163,4597],{"class":127},[87,7165,7166,7168],{"class":89,"line":137},[87,7167,3913],{"class":111},[87,7169,3930],{"class":127},[87,7171,7172],{"class":89,"line":431},[87,7173,399],{"emptyLinePlaceholder":398},[87,7175,7176],{"class":89,"line":436},[87,7177,399],{"emptyLinePlaceholder":398},[87,7179,7180,7182,7185,7187,7189],{"class":89,"line":1445},[87,7181,28],{"class":111},[87,7183,7184],{"class":93}," opencv_function7",[87,7186,124],{"class":97},[87,7188,3636],{"class":111},[87,7190,3010],{"class":97},[87,7192,7193],{"class":89,"line":1451},[87,7194,1411],{"class":97},[87,7196,7197,7199,7201,7203,7205,7207],{"class":89,"line":1477},[87,7198,3960],{"class":93},[87,7200,4635],{"class":97},[87,7202,4638],{"class":93},[87,7204,124],{"class":97},[87,7206,1042],{"class":231},[87,7208,1257],{"class":97},[87,7210,7211,7213],{"class":89,"line":1483},[87,7212,3960],{"class":93},[87,7214,4855],{"class":97},[87,7216,7217,7219,7221,7223,7225,7227,7229,7231],{"class":89,"line":2214},[87,7218,3264],{"class":111},[87,7220,4662],{"class":97},[87,7222,4665],{"class":93},[87,7224,4668],{"class":97},[87,7226,3280],{"class":111},[87,7228,4673],{"class":231},[87,7230,1403],{"class":97},[87,7232,4678],{"class":101},[87,7234,7235],{"class":89,"line":4013},[87,7236,1448],{"class":97},[87,7238,7239,7241,7243,7245,7247,7249,7251,7253,7255,7257],{"class":89,"line":4036},[87,7240,4687],{"class":93},[87,7242,124],{"class":97},[87,7244,4692],{"class":127},[87,7246,4695],{"class":231},[87,7248,4698],{"class":127},[87,7250,4701],{"class":97},[87,7252,4704],{"class":93},[87,7254,124],{"class":97},[87,7256,94],{"class":93},[87,7258,4711],{"class":97},[87,7260,7261,7263,7265,7267,7269,7271,7273,7275,7277,7279],{"class":89,"line":4041},[87,7262,4687],{"class":93},[87,7264,124],{"class":97},[87,7266,4720],{"class":127},[87,7268,4695],{"class":231},[87,7270,4698],{"class":127},[87,7272,4701],{"class":97},[87,7274,4704],{"class":93},[87,7276,124],{"class":97},[87,7278,94],{"class":93},[87,7280,4735],{"class":97},[87,7282,7283,7285,7287,7289,7291,7293,7295,7297,7299,7301],{"class":89,"line":4060},[87,7284,4687],{"class":93},[87,7286,124],{"class":97},[87,7288,4744],{"class":127},[87,7290,4695],{"class":231},[87,7292,4698],{"class":127},[87,7294,4701],{"class":97},[87,7296,4704],{"class":93},[87,7298,124],{"class":97},[87,7300,94],{"class":93},[87,7302,4759],{"class":97},[87,7304,7305,7307,7309,7311,7313,7315,7317,7319,7321,7323],{"class":89,"line":4238},[87,7306,4687],{"class":93},[87,7308,124],{"class":97},[87,7310,4768],{"class":127},[87,7312,4695],{"class":231},[87,7314,4698],{"class":127},[87,7316,4701],{"class":97},[87,7318,4704],{"class":93},[87,7320,124],{"class":97},[87,7322,94],{"class":93},[87,7324,4783],{"class":97},[87,7326,7327],{"class":89,"line":4255},[87,7328,1480],{"class":97},[87,7330,7331],{"class":89,"line":4260},[87,7332,4792],{"class":111},[87,7334,7335],{"class":89,"line":4799},[87,7336,1448],{"class":97},[87,7338,7339,7341,7343,7346],{"class":89,"line":4811},[87,7340,4687],{"class":93},[87,7342,124],{"class":97},[87,7344,7345],{"class":127},"\"导入摄像头视频失败，请确认摄像头是否正常打开\"",[87,7347,1257],{"class":97},[87,7349,7350,7352,7354],{"class":89,"line":4821},[87,7351,4814],{"class":111},[87,7353,1217],{"class":231},[87,7355,2211],{"class":97},[87,7357,7358],{"class":89,"line":4826},[87,7359,1480],{"class":97},[87,7361,7362,7364,7366,7369],{"class":89,"line":4831},[87,7363,5582],{"class":93},[87,7365,124],{"class":97},[87,7367,7368],{"class":127},"\"按下空格键截图!\"",[87,7370,1257],{"class":97},[87,7372,7373,7375,7377,7380],{"class":89,"line":4844},[87,7374,5582],{"class":93},[87,7376,124],{"class":97},[87,7378,7379],{"class":127},"\"按下ESC结束播放!\"",[87,7381,1257],{"class":97},[87,7383,7384,7386,7388,7390],{"class":89,"line":4849},[87,7385,4834],{"class":111},[87,7387,124],{"class":97},[87,7389,4839],{"class":231},[87,7391,3010],{"class":97},[87,7393,7394],{"class":89,"line":4858},[87,7395,1448],{"class":97},[87,7397,7398,7400,7402],{"class":89,"line":4869},[87,7399,4861],{"class":97},[87,7401,4390],{"class":111},[87,7403,4866],{"class":97},[87,7405,7406,7408,7410,7412,7414,7416],{"class":89,"line":4892},[87,7407,4852],{"class":93},[87,7409,118],{"class":97},[87,7411,3821],{"class":93},[87,7413,124],{"class":97},[87,7415,7014],{"class":127},[87,7417,4926],{"class":97},[87,7419,7420,7423,7426,7428,7430,7432,7434,7436,7438,7440,7443,7445,7447,7449],{"class":89,"line":4898},[87,7421,7422],{"class":111},"        int32_t",[87,7424,7425],{"class":97}," key_boards_val ",[87,7427,112],{"class":111},[87,7429,115],{"class":93},[87,7431,118],{"class":97},[87,7433,4048],{"class":93},[87,7435,124],{"class":97},[87,7437,4940],{"class":231},[87,7439,1856],{"class":111},[87,7441,7442],{"class":97},"video__.",[87,7444,4704],{"class":93},[87,7446,124],{"class":97},[87,7448,94],{"class":93},[87,7450,4759],{"class":97},[87,7452,7453,7455,7458,7460,7463,7465],{"class":89,"line":4906},[87,7454,4872],{"class":111},[87,7456,7457],{"class":97},"(key_boards_val",[87,7459,3280],{"class":111},[87,7461,7462],{"class":231},"32",[87,7464,1403],{"class":97},[87,7466,7467],{"class":101},"   //检测到按下了空格键\n",[87,7469,7470],{"class":89,"line":4912},[87,7471,4895],{"class":97},[87,7473,7474,7477,7479,7481,7483,7485,7487,7489,7491,7493,7495,7497,7500,7503,7505,7507],{"class":89,"line":4929},[87,7475,7476],{"class":111},"            if",[87,7478,124],{"class":97},[87,7480,94],{"class":93},[87,7482,118],{"class":97},[87,7484,5135],{"class":93},[87,7486,124],{"class":97},[87,7488,3976],{"class":93},[87,7490,118],{"class":97},[87,7492,24],{"class":93},[87,7494,5535],{"class":97},[87,7496,1471],{"class":111},[87,7498,7499],{"class":127}," \"chapter2_4_save_media_file/save_files/save_image_test2.png\"",[87,7501,7502],{"class":97},",frame__) ",[87,7504,3280],{"class":111},[87,7506,5548],{"class":231},[87,7508,3010],{"class":97},[87,7510,7511],{"class":89,"line":4961},[87,7512,7513],{"class":97},"            {\n",[87,7515,7516,7519,7521,7524],{"class":89,"line":4966},[87,7517,7518],{"class":93},"                printf",[87,7520,124],{"class":97},[87,7522,7523],{"class":127},"\"截图失败!\"",[87,7525,1257],{"class":97},[87,7527,7528],{"class":89,"line":4984},[87,7529,7530],{"class":97},"            }\n",[87,7532,7533],{"class":89,"line":5743},[87,7534,7535],{"class":111},"            else\n",[87,7537,7538],{"class":89,"line":5749},[87,7539,7513],{"class":97},[87,7541,7542,7544,7546,7549],{"class":89,"line":5755},[87,7543,7518],{"class":93},[87,7545,124],{"class":97},[87,7547,7548],{"class":127},"\"截图成功!\"",[87,7550,1257],{"class":97},[87,7552,7553],{"class":89,"line":5761},[87,7554,7530],{"class":97},[87,7556,7557,7559,7561,7563,7565,7567,7569,7571],{"class":89,"line":5792},[87,7558,7476],{"class":111},[87,7560,4875],{"class":97},[87,7562,4878],{"class":93},[87,7564,4668],{"class":97},[87,7566,3280],{"class":111},[87,7568,4673],{"class":231},[87,7570,1403],{"class":97},[87,7572,4889],{"class":101},[87,7574,7575],{"class":89,"line":5828},[87,7576,7513],{"class":97},[87,7578,7579,7581,7583,7586],{"class":89,"line":5861},[87,7580,7518],{"class":93},[87,7582,124],{"class":97},[87,7584,7585],{"class":127},"\"视频播放结束,请选择截图或是按ESC退出!\"",[87,7587,1257],{"class":97},[87,7589,7590],{"class":89,"line":5891},[87,7591,7530],{"class":97},[87,7593,7594],{"class":89,"line":5922},[87,7595,4909],{"class":97},[87,7597,7598,7601,7604,7606,7608,7611,7613],{"class":89,"line":5927},[87,7599,7600],{"class":111},"        else",[87,7602,7603],{"class":111}," if",[87,7605,7457],{"class":97},[87,7607,3280],{"class":111},[87,7609,7610],{"class":231},"27",[87,7612,1403],{"class":97},[87,7614,7615],{"class":101},"   //检测到按下了ESC按键\n",[87,7617,7618],{"class":89,"line":5933},[87,7619,4895],{"class":97},[87,7621,7622,7624],{"class":89,"line":6710},[87,7623,6979],{"class":111},[87,7625,2211],{"class":97},[87,7627,7628],{"class":89,"line":6724},[87,7629,4909],{"class":97},[87,7631,7632],{"class":89,"line":6763},[87,7633,1480],{"class":97},[87,7635,7636,7639,7641],{"class":89,"line":6779},[87,7637,7638],{"class":97},"    video__.",[87,7640,7117],{"class":93},[87,7642,519],{"class":97},[87,7644,7645,7647,7649,7652],{"class":89,"line":6796},[87,7646,5582],{"class":93},[87,7648,124],{"class":97},[87,7650,7651],{"class":127},"\"播放被终止或已结束!\"",[87,7653,1257],{"class":97},[87,7655,7656],{"class":89,"line":6819},[87,7657,399],{"emptyLinePlaceholder":398},[87,7659,7660,7662,7664],{"class":89,"line":6831},[87,7661,5594],{"class":111},[87,7663,1389],{"class":231},[87,7665,2211],{"class":97},[87,7667,7668],{"class":89,"line":6836},[87,7669,1486],{"class":97},[42,7671,7673],{"id":7672},"save-and-read-xml-and-yaml-files","Save and read XML and YAML files",[10,7675,7676,7677,170,7680,7683,7684,7687,7688,7691,7692,7695,7696,7698],{},"Besides image data, sometimes smaller-sized Mat matrices, strings, arrays, and other data in a program also need to be saved. This data is typically stored as XML or YAML files. This section introduces how to use functions in OpenCV 4 to save data as XML or YAML files, as well as how to read data from these two file formats.\nXML is a meta-markup language. By \"meta-markup,\" it means that users can define their own tags based on their needs. For example, tags like ",[22,7678,7679],{},"\u003Cage>",[22,7681,7682],{},"\u003Ccolor>"," can be used to define the meaning of data, such as using ",[22,7685,7686],{},"\u003Cage>24\u003C/age>"," to indicate that the value of the age data is 24. XML is a structured language that allows you to understand the hierarchical relationships between data. For instance, ",[22,7689,7690],{},"\u003Ccolor>\u003Cred>100\u003C/red>\u003Cblue>150\u003C/blue>\u003C/color>"," indicates that within the color data, there are two pieces of data named red and blue, with values of 100 and 150 respectively. By using tags, no matter how the data is stored, as long as the file conforms to the XML format, the data read out will be free from confusion and ambiguity.\nYAML is a data-centric language that represents each data value in the form of \"variable: value\" and uses different levels of indentation to indicate the structure and hierarchical relationships between data. YAML is highly readable and is often used to express data serialization formats. It draws inspiration from multiple languages, including XML, C, Python, and Perl.\nOpenCV 4 provides the ",[22,7693,7694],{},"FileStorage"," class for generating and reading XML and YAML files. This class defines methods for initializing the class, writing data, and reading data. When using the ",[22,7697,7694],{}," class, it must first be initialized, which can be understood as declaring the file to be operated on and the type of operation. OpenCV 4 offers two initialization methods: one without any parameters (which can be thought of as merely declaring the object without initializing it), and another that takes a file name and operation type as input. The prototype of the constructor for the latter initialization method is given in Code Listing 2-35.\nCode Listing 2-35 FileStorage() function prototype",[78,7700,7702],{"className":80,"code":7701,"language":82,"meta":83,"style":83},"cv::FileStorage::FileStorage(const String &filename,\n                             int flags,\n                             const String &encoding = String());\n",[22,7703,7704,7728,7735],{"__ignoreMap":83},[87,7705,7706,7708,7710,7712,7714,7716,7718,7720,7723,7725],{"class":89,"line":90},[87,7707,94],{"class":93},[87,7709,118],{"class":97},[87,7711,7694],{"class":93},[87,7713,118],{"class":97},[87,7715,7694],{"class":93},[87,7717,124],{"class":97},[87,7719,731],{"class":111},[87,7721,7722],{"class":97}," String ",[87,7724,737],{"class":111},[87,7726,7727],{"class":97},"filename,\n",[87,7729,7730,7732],{"class":89,"line":105},[87,7731,6004],{"class":111},[87,7733,7734],{"class":97}," flags,\n",[87,7736,7737,7740,7742,7744,7747,7749,7751],{"class":89,"line":137},[87,7738,7739],{"class":111},"                             const",[87,7741,7722],{"class":97},[87,7743,737],{"class":111},[87,7745,7746],{"class":97},"encoding ",[87,7748,112],{"class":111},[87,7750,3444],{"class":93},[87,7752,826],{"class":97},[566,7754,7755,7758,7761],{},[569,7756,7757],{},"filename: The name of the opened file.",[569,7759,7760],{},"flags: The type of operation flag applied to the file. Common parameters and their meanings are given in Table 2-8.",[569,7762,7763],{},"encoding: Encoding format. UTF-16 XML encoding is currently not supported; UTF-8 XML encoding must be used.\nTable 2-8 Common flags and their meanings for file operation types in the FileStorage() constructor",[253,7765,7766,7777],{},[256,7767,7768],{},[259,7769,7770,7772,7774],{},[262,7771,3511],{"align":2459},[262,7773,3514],{"align":2459},[262,7775,7776],{"align":2459},"Meaning",[272,7778,7779,7789,7799,7809],{},[259,7780,7781,7784,7786],{},[277,7782,7783],{"align":2459},"READ",[277,7785,1042],{"align":2459},[277,7787,7788],{"align":2459},"Read the data from the file.",[259,7790,7791,7794,7796],{},[277,7792,7793],{"align":2459},"WRITE",[277,7795,1562],{"align":2459},[277,7797,7798],{"align":2459},"Writing data back to the file will overwrite the previous data.",[259,7800,7801,7804,7806],{},[277,7802,7803],{"align":2459},"APPEND",[277,7805,871],{"align":2459},[277,7807,7808],{"align":2459},"Continue writing data to the file, appending the new data after the existing data.",[259,7810,7811,7814,7816],{},[277,7812,7813],{"align":2459},"MEMORY",[277,7815,1230],{"align":2459},[277,7817,7818],{"align":2459},"Write data to or read data from the internal buffer.",[10,7820,7821,7822,7824,7825,7827,7828,7831],{},"This function is the constructor of the ",[22,7823,7694],{}," class, used to declare the name of the file to be opened and the type of operation. The first parameter is the name of the file to be opened, which is a string type, and the file extension is either \".xml\" or \".yaml\" (or \".yml\"). The file to be opened may already exist or not, but when performing a read operation on the file, it must already exist. The second parameter is the operation type flag for the file, such as reading or writing. Common parameters and their meanings are given in Table 2-8. Since this flag belongs to the ",[22,7826,7694],{}," class, the class name must be used as a prefix when using it, for example, ",[22,7829,7830],{},"FileStorage::WRITE",". The last parameter is the file's encoding format. UTF-16 XML encoding is currently not supported; UTF-8 XML encoding must be used. In most cases, the default value of this parameter can be used.",[10,7833,7834,7835,7837,7838,7840,7841,7843,7844,1159],{},"After opening a file, you can use the ",[22,7836,6074],{}," function in the ",[22,7839,7694],{}," class to check whether the file was successfully opened. If the file opens successfully, the function returns ",[22,7842,4839],{},"; if it fails to open, the function returns ",[22,7845,7846],{},"false",[10,7848,7849],{},"Since the default constructor in the FileStorage class has no parameters, it does not declare the opened file or the type of operation. In this case, the open() function in the FileStorage class must be used to declare them separately. The prototype of this function is given in Code Listing 2-36.",[10,7851,7852],{},"Code Listing 2-36 open() function prototype",[78,7854,7856],{"className":80,"code":7855,"language":82,"meta":83,"style":83},"virtual bool cv::FileStorage::open(const String &filename,\n                                    int flags,\n                                    const String &encoding = String());\n",[22,7857,7858,7888,7897],{"__ignoreMap":83},[87,7859,7860,7863,7866,7868,7870,7872,7874,7876,7878,7880,7882,7884,7886],{"class":89,"line":90},[87,7861,7862],{"class":111},"virtual",[87,7864,7865],{"class":111}," bool",[87,7867,115],{"class":93},[87,7869,118],{"class":97},[87,7871,7694],{"class":93},[87,7873,118],{"class":97},[87,7875,6825],{"class":93},[87,7877,124],{"class":97},[87,7879,731],{"class":111},[87,7881,3444],{"class":93},[87,7883,3447],{"class":111},[87,7885,3451],{"class":3450},[87,7887,3454],{"class":97},[87,7889,7890,7893,7895],{"class":89,"line":105},[87,7891,7892],{"class":111},"                                    int",[87,7894,3462],{"class":3450},[87,7896,3454],{"class":97},[87,7898,7899,7902,7904,7906,7909,7911,7913],{"class":89,"line":137},[87,7900,7901],{"class":111},"                                    const",[87,7903,3444],{"class":93},[87,7905,3447],{"class":111},[87,7907,7908],{"class":3450},"encoding",[87,7910,3465],{"class":111},[87,7912,3444],{"class":93},[87,7914,826],{"class":97},[566,7916,7917,7919,7921],{},[569,7918,7757],{},[569,7920,7760],{},[569,7922,7923,7924,7926,7927,7837,7929,7931],{},"encoding: Encoding format. UTF-16 XML encoding is currently not supported; UTF-8 XML encoding must be used.\nThis function solves the problem that the default constructor does not declare opening a file. The function can specify the file opened by the FileStorage class. If the file is successfully opened, the return value is true; otherwise, it is false. All parameters and their meanings in this function are the same as those in Code Listing 2-35, so they will not be repeated here. Similarly, after opening a file using this function, you can still use the ",[22,7925,6074],{}," function in the FileStorage class to check whether the file was successfully opened.\nAfter opening a file, similar to creating a data stream in C++, you can use the \"\u003C\u003C\" operator to write data into the file, or the \">>\" operator to read data from the file. Additionally, you can write data to the file using the ",[22,7928,6084],{},[22,7930,7694],{}," class, whose prototype is given in Code Listing 2-37.\nCode Listing 2-37 write() function prototype",[78,7933,7935],{"className":80,"code":7934,"language":82,"meta":83,"style":83},"void cv::FileStorage::write(const String &name,\n                            int val);\n",[22,7936,7937,7965],{"__ignoreMap":83},[87,7938,7939,7941,7943,7945,7947,7949,7952,7954,7956,7958,7960,7963],{"class":89,"line":90},[87,7940,3636],{"class":111},[87,7942,115],{"class":93},[87,7944,118],{"class":97},[87,7946,7694],{"class":93},[87,7948,118],{"class":97},[87,7950,7951],{"class":93},"write",[87,7953,124],{"class":97},[87,7955,731],{"class":111},[87,7957,3444],{"class":93},[87,7959,3447],{"class":111},[87,7961,7962],{"class":3450},"name",[87,7964,3454],{"class":97},[87,7966,7967,7970,7973],{"class":89,"line":105},[87,7968,7969],{"class":111},"                            int",[87,7971,7972],{"class":3450}," val",[87,7974,1257],{"class":97},[566,7976,7977,7980],{},[569,7978,7979],{},"name: The variable name written in the file.",[569,7981,7982],{},"val: variable value.",[10,7984,7985,7986,1159],{},"This function can write variable names and values of different data types into a file. The first parameter of the function is the variable name to be written into the file. The second parameter is the variable value. In Code Listing 2-37, the variable value is of type int, but the FileStorage class provides multiple overloaded functions of write(), each used to write ",[22,7987,7988],{},"double、String、Mat、vector\u003CString>",[10,7990,7991,7992,7994,7995,7998,7999,8002,8003,8006,8007,8010,8011,1159],{},"When using operators to write data to a file, it is similar to the ",[22,7993,6084],{}," function in that both require declaring variable names and variable values. For example, if the variable name is \"age\" and the variable value is \"24\", this can be achieved with ",[22,7996,7997],{},"file \u003C\u003C \"age\" \u003C\u003C 24",". If a variable's data is an array, you can use ",[22,8000,8001],{},"[]"," to mark the values belonging to the same variable, e.g., ",[22,8004,8005],{},"file \u003C\u003C \"age\" \u003C\u003C \"[\" \u003C\u003C 24 \u003C\u003C 25 \u003C\u003C \"]\"",". If some variables belong to another variable, you can use ",[22,8008,8009],{},"{}"," to indicate the hierarchical relationship between variables, e.g., ",[22,8012,8013],{},"file \u003C\u003C \"age\" \u003C\u003C \"{\" \u003C\u003C \"Xiaoming\" \u003C\u003C 24 \u003C\u003C \"Wanghua\" \u003C\u003C 25 \u003C\u003C \"}\"",[10,8015,8016,8017,8020,8021,8024,8025,8028,8029,8032,8033,8035,8036,8039,8040,8042,8043,8046,8047,8050,8051,8054,8055,8058,8059,8061],{},"When reading data, you can use ",[22,8018,8019],{},"file[\"x\"] >> xRead"," to read the value of a variable named ",[22,8022,8023],{},"x",". However, when a variable contains multiple data points or sub-variables, you need to use the ",[22,8026,8027],{},"FileNode"," node type and the ",[22,8030,8031],{},"FileNodeIterator"," iterator to read it. For example, if a variable's value is an array, you first define a ",[22,8034,8027],{}," node variable like ",[22,8037,8038],{},"file[\"age\"]",", and then iterate through the data using the iterator. Another method avoids using an iterator by appending ",[22,8041,8001],{}," (address) after the variable, such as ",[22,8044,8045],{},"FileNode[0]"," to access the first element in the array variable, or ",[22,8048,8049],{},"FileNode[\"Xiaoming\"]"," to access the data of the ",[22,8052,8053],{},"\"Xiaoming\""," variable within the ",[22,8056,8057],{},"\"age\""," variable. By chaining ",[22,8060,8001],{}," (address) in this way, you can read data from multiple nodes.",[10,8063,8064,8065,8067,8068,8070,8071,8073],{},"To understand how to generate and read XML and YAML files, Code Listing 2-38 provides an example program that implements file writing and reading. This program uses both the ",[22,8066,6084],{}," function and the ",[22,8069,1214],{}," operator to write data to files, and uses both iterators and ",[22,8072,8001],{}," (address) to read data from files. The methods for writing and reading data have been introduced earlier; in Code Listing 2-38, the key focus is on understanding how to implement writing and reading through code. The data in the XML and YAML files generated by this program is shown in Figure 2-9, and the results of reading the file data are shown in Figure 2-10.",[10,8075,8076],{},"Code Listing 2-38 myXMLandYAML.cpp: Saving and Reading XML and YAML Files",[78,8078,8080],{"className":80,"code":8079,"language":82,"meta":83,"style":83},"#include \"chapter2_4_save_media_file/inc/save_XMLandYMAL.hpp\"\n#include \u003Ccstdio>\n#include \u003Copencv2/opencv.hpp>\n\nusing namespace std;\nusing namespace cv;\n\nint opencv_function8(void)\n{\nsystem(\"color F0\");  //修改运行程序背景和文字颜色\n    // string fileName = std::string(SRCSRC_PATH) + \"chapter2_4_save_media_file/save_files/datas.xml\";  //文件的名称\n    string fileName = std::string(SRCSRC_PATH) + \"chapter2_4_save_media_file/save_files/datas.yaml\"; //文件的名称\n    //以写入的模式打开文件\n    cv::FileStorage fwrite(fileName, cv::FileStorage::WRITE);\n    \n    //存入矩阵Mat类型的数据\n    Mat mat = Mat::eye(3, 3, CV_8U);\n    fwrite.write(\"mat\", mat);  //使用write()函数写入数据\n    //存入浮点型数据，节点名称为x\n    float x = 100;\n    fwrite \u003C\u003C \"x\" \u003C\u003C x;\n    //存入字符串型数据，节点名称为str\n    String str = \"Learn OpenCV 4\";\n    fwrite \u003C\u003C \"str\" \u003C\u003C str;\n    //存入数组,节点名称为number_array\n    fwrite \u003C\u003C \"number_array\" \u003C\u003C \"[\" \u003C\u003C4\u003C\u003C5\u003C\u003C6\u003C\u003C \"]\";\n    //存入多node节点数据,主名称为multi_nodes\n    fwrite \u003C\u003C \"multi_nodes\" \u003C\u003C \"{\" \u003C\u003C \"month\" \u003C\u003C 8 \u003C\u003C \"day\" \u003C\u003C 28 \u003C\u003C \"year\"\n        \u003C\u003C 2019 \u003C\u003C \"time\" \u003C\u003C \"[\" \u003C\u003C 0 \u003C\u003C 1 \u003C\u003C 2 \u003C\u003C 3 \u003C\u003C \"]\" \u003C\u003C \"}\";\n\n    //关闭文件\n    fwrite.release();\n\n    //以读取的模式打开文件\n    cv::FileStorage fread(fileName, cv::FileStorage::READ);\n    //判断是否成功打开文件\n    if (!fread.isOpened())\n    {\n        cout \u003C\u003C \"打开文件失败，请确认文件名称是否正确！\" \u003C\u003C endl;\n        return -1;\n    }\n\n    //读取文件中的数据\n    float xRead;\n    fread[\"x\"] >> xRead;  //读取浮点型数据\n    cout \u003C\u003C \"x=\" \u003C\u003C xRead \u003C\u003C endl;\n\n    //读取字符串数据\n    string strRead;\n    fread[\"str\"] >> strRead;\n    cout \u003C\u003C \"str=\" \u003C\u003C strRead \u003C\u003C endl;\n\n    //读取含多个数据的number_array节点\n    FileNode fileNode = fread[\"number_array\"];\n    cout \u003C\u003C \"number_array=[\";\n    //循环遍历每个数据\n    for (FileNodeIterator i = fileNode.begin(); i != fileNode.end(); i++)\n    {\n        float a;\n        *i >> a;\n        cout \u003C\u003C a\u003C\u003C\" \";\n    }\n    cout \u003C\u003C \"]\" \u003C\u003C endl;\n\n    //读取Mat类型数据\n    Mat matRead;\n    fread[\"mat=\"] >> matRead;\n    cout \u003C\u003C \"mat=\" \u003C\u003C mat \u003C\u003C endl;\n\n    //读取含有多个子节点的节点数据，不使用FileNode和迭代器进行读取\n    FileNode fileNode1 = fread[\"multi_nodes\"];\n    int month = (int)fileNode1[\"month\"];\n    int day = (int)fileNode1[\"day\"];\n    int year = (int)fileNode1[\"year\"];\n    cout \u003C\u003C \"multi_nodes:\" \u003C\u003C endl \n        \u003C\u003C \"  month=\" \u003C\u003C month \u003C\u003C \"  day=\" \u003C\u003C day \u003C\u003C \"  year=\" \u003C\u003C year;\n    cout \u003C\u003C \"  time=[\";\n    for (int i = 0; i \u003C 4; i++)\n    {\n        int a = (int)fileNode1[\"time\"][i];\n        cout \u003C\u003C a \u003C\u003C \" \";\n    }\n    cout \u003C\u003C \"]\" \u003C\u003C endl;\n    \n    //关闭文件\n    fread.release();\n    return 0;\n}\n",[22,8081,8082,8089,8095,8101,8105,8117,8127,8131,8144,8148,8163,8171,8197,8202,8224,8228,8233,8258,8276,8281,8296,8311,8316,8328,8342,8347,8380,8385,8424,8469,8473,8478,8486,8490,8495,8515,8520,8537,8541,8554,8565,8569,8573,8578,8585,8603,8621,8625,8630,8635,8649,8667,8671,8676,8691,8702,8707,8739,8743,8750,8761,8776,8780,8792,8796,8801,8806,8820,8838,8842,8847,8861,8882,8902,8922,8936,8966,8977,9004,9008,9029,9043,9047,9060,9065,9070,9080,9089],{"__ignoreMap":83},[87,8083,8084,8086],{"class":89,"line":90},[87,8085,3913],{"class":111},[87,8087,8088],{"class":127}," \"chapter2_4_save_media_file/inc/save_XMLandYMAL.hpp\"\n",[87,8090,8091,8093],{"class":89,"line":105},[87,8092,3913],{"class":111},[87,8094,4597],{"class":127},[87,8096,8097,8099],{"class":89,"line":137},[87,8098,3913],{"class":111},[87,8100,3930],{"class":127},[87,8102,8103],{"class":89,"line":431},[87,8104,399],{"emptyLinePlaceholder":398},[87,8106,8107,8110,8113,8115],{"class":89,"line":436},[87,8108,8109],{"class":111},"using",[87,8111,8112],{"class":111}," namespace",[87,8114,4030],{"class":93},[87,8116,2211],{"class":97},[87,8118,8119,8121,8123,8125],{"class":89,"line":1445},[87,8120,8109],{"class":111},[87,8122,8112],{"class":111},[87,8124,115],{"class":93},[87,8126,2211],{"class":97},[87,8128,8129],{"class":89,"line":1451},[87,8130,399],{"emptyLinePlaceholder":398},[87,8132,8133,8135,8138,8140,8142],{"class":89,"line":1477},[87,8134,28],{"class":111},[87,8136,8137],{"class":93}," opencv_function8",[87,8139,124],{"class":97},[87,8141,3636],{"class":111},[87,8143,3010],{"class":97},[87,8145,8146],{"class":89,"line":1483},[87,8147,1411],{"class":97},[87,8149,8150,8153,8155,8158,8160],{"class":89,"line":2214},[87,8151,8152],{"class":93},"system",[87,8154,124],{"class":97},[87,8156,8157],{"class":127},"\"color F0\"",[87,8159,131],{"class":97},[87,8161,8162],{"class":101},"  //修改运行程序背景和文字颜色\n",[87,8164,8165,8168],{"class":89,"line":4013},[87,8166,8167],{"class":101},"    // string fileName = std::string(SRCSRC_PATH) + \"chapter2_4_save_media_file/save_files/datas.xml\";",[87,8169,8170],{"class":101},"  //文件的名称\n",[87,8172,8173,8176,8178,8180,8182,8184,8186,8188,8191,8194],{"class":89,"line":4036},[87,8174,8175],{"class":97},"    string fileName ",[87,8177,112],{"class":111},[87,8179,4030],{"class":93},[87,8181,118],{"class":97},[87,8183,24],{"class":93},[87,8185,5535],{"class":97},[87,8187,1471],{"class":111},[87,8189,8190],{"class":127}," \"chapter2_4_save_media_file/save_files/datas.yaml\"",[87,8192,8193],{"class":97},";",[87,8195,8196],{"class":101}," //文件的名称\n",[87,8198,8199],{"class":89,"line":4041},[87,8200,8201],{"class":101},"    //以写入的模式打开文件\n",[87,8203,8204,8206,8209,8212,8215,8217,8219,8221],{"class":89,"line":4060},[87,8205,3960],{"class":93},[87,8207,8208],{"class":97},"::FileStorage ",[87,8210,8211],{"class":93},"fwrite",[87,8213,8214],{"class":97},"(fileName, ",[87,8216,94],{"class":93},[87,8218,118],{"class":97},[87,8220,7694],{"class":93},[87,8222,8223],{"class":97},"::WRITE);\n",[87,8225,8226],{"class":89,"line":4238},[87,8227,6407],{"class":97},[87,8229,8230],{"class":89,"line":4255},[87,8231,8232],{"class":101},"    //存入矩阵Mat类型的数据\n",[87,8234,8235,8238,8240,8243,8245,8247,8249,8251,8253,8255],{"class":89,"line":4260},[87,8236,8237],{"class":97},"    Mat mat ",[87,8239,112],{"class":111},[87,8241,8242],{"class":93}," Mat",[87,8244,118],{"class":97},[87,8246,1526],{"class":93},[87,8248,124],{"class":97},[87,8250,232],{"class":231},[87,8252,235],{"class":97},[87,8254,232],{"class":231},[87,8256,8257],{"class":97},", CV_8U);\n",[87,8259,8260,8263,8265,8267,8270,8273],{"class":89,"line":4799},[87,8261,8262],{"class":97},"    fwrite.",[87,8264,7951],{"class":93},[87,8266,124],{"class":97},[87,8268,8269],{"class":127},"\"mat\"",[87,8271,8272],{"class":97},", mat);",[87,8274,8275],{"class":101},"  //使用write()函数写入数据\n",[87,8277,8278],{"class":89,"line":4811},[87,8279,8280],{"class":101},"    //存入浮点型数据，节点名称为x\n",[87,8282,8283,8286,8289,8291,8294],{"class":89,"line":4821},[87,8284,8285],{"class":111},"    float",[87,8287,8288],{"class":97}," x ",[87,8290,112],{"class":111},[87,8292,8293],{"class":231}," 100",[87,8295,2211],{"class":97},[87,8297,8298,8301,8303,8306,8308],{"class":89,"line":4826},[87,8299,8300],{"class":97},"    fwrite ",[87,8302,1214],{"class":111},[87,8304,8305],{"class":127}," \"x\"",[87,8307,4027],{"class":111},[87,8309,8310],{"class":97}," x;\n",[87,8312,8313],{"class":89,"line":4831},[87,8314,8315],{"class":101},"    //存入字符串型数据，节点名称为str\n",[87,8317,8318,8321,8323,8326],{"class":89,"line":4844},[87,8319,8320],{"class":97},"    String str ",[87,8322,112],{"class":111},[87,8324,8325],{"class":127}," \"Learn OpenCV 4\"",[87,8327,2211],{"class":97},[87,8329,8330,8332,8334,8337,8339],{"class":89,"line":4849},[87,8331,8300],{"class":97},[87,8333,1214],{"class":111},[87,8335,8336],{"class":127}," \"str\"",[87,8338,4027],{"class":111},[87,8340,8341],{"class":97}," str;\n",[87,8343,8344],{"class":89,"line":4858},[87,8345,8346],{"class":101},"    //存入数组,节点名称为number_array\n",[87,8348,8349,8351,8353,8356,8358,8361,8363,8365,8367,8369,8371,8373,8375,8378],{"class":89,"line":4869},[87,8350,8300],{"class":97},[87,8352,1214],{"class":111},[87,8354,8355],{"class":127}," \"number_array\"",[87,8357,4027],{"class":111},[87,8359,8360],{"class":127}," \"[\"",[87,8362,4027],{"class":111},[87,8364,1230],{"class":231},[87,8366,1214],{"class":111},[87,8368,876],{"class":231},[87,8370,1214],{"class":111},[87,8372,1239],{"class":231},[87,8374,1214],{"class":111},[87,8376,8377],{"class":127}," \"]\"",[87,8379,2211],{"class":97},[87,8381,8382],{"class":89,"line":4892},[87,8383,8384],{"class":101},"    //存入多node节点数据,主名称为multi_nodes\n",[87,8386,8387,8389,8391,8394,8396,8399,8401,8404,8406,8409,8411,8414,8416,8419,8421],{"class":89,"line":4898},[87,8388,8300],{"class":97},[87,8390,1214],{"class":111},[87,8392,8393],{"class":127}," \"multi_nodes\"",[87,8395,4027],{"class":111},[87,8397,8398],{"class":127}," \"{\"",[87,8400,4027],{"class":111},[87,8402,8403],{"class":127}," \"month\"",[87,8405,4027],{"class":111},[87,8407,8408],{"class":231}," 8",[87,8410,4027],{"class":111},[87,8412,8413],{"class":127}," \"day\"",[87,8415,4027],{"class":111},[87,8417,8418],{"class":231}," 28",[87,8420,4027],{"class":111},[87,8422,8423],{"class":127}," \"year\"\n",[87,8425,8426,8429,8432,8434,8437,8439,8441,8443,8445,8447,8449,8451,8453,8455,8458,8460,8462,8464,8467],{"class":89,"line":4906},[87,8427,8428],{"class":111},"        \u003C\u003C",[87,8430,8431],{"class":231}," 2019",[87,8433,4027],{"class":111},[87,8435,8436],{"class":127}," \"time\"",[87,8438,4027],{"class":111},[87,8440,8360],{"class":127},[87,8442,4027],{"class":111},[87,8444,1389],{"class":231},[87,8446,4027],{"class":111},[87,8448,1217],{"class":231},[87,8450,4027],{"class":111},[87,8452,2187],{"class":231},[87,8454,4027],{"class":111},[87,8456,8457],{"class":231}," 3",[87,8459,4027],{"class":111},[87,8461,8377],{"class":127},[87,8463,4027],{"class":111},[87,8465,8466],{"class":127}," \"}\"",[87,8468,2211],{"class":97},[87,8470,8471],{"class":89,"line":4912},[87,8472,399],{"emptyLinePlaceholder":398},[87,8474,8475],{"class":89,"line":4929},[87,8476,8477],{"class":101},"    //关闭文件\n",[87,8479,8480,8482,8484],{"class":89,"line":4961},[87,8481,8262],{"class":97},[87,8483,7117],{"class":93},[87,8485,519],{"class":97},[87,8487,8488],{"class":89,"line":4966},[87,8489,399],{"emptyLinePlaceholder":398},[87,8491,8492],{"class":89,"line":4984},[87,8493,8494],{"class":101},"    //以读取的模式打开文件\n",[87,8496,8497,8499,8501,8504,8506,8508,8510,8512],{"class":89,"line":5743},[87,8498,3960],{"class":93},[87,8500,8208],{"class":97},[87,8502,8503],{"class":93},"fread",[87,8505,8214],{"class":97},[87,8507,94],{"class":93},[87,8509,118],{"class":97},[87,8511,7694],{"class":93},[87,8513,8514],{"class":97},"::READ);\n",[87,8516,8517],{"class":89,"line":5749},[87,8518,8519],{"class":101},"    //判断是否成功打开文件\n",[87,8521,8522,8524,8526,8529,8532,8534],{"class":89,"line":5755},[87,8523,3264],{"class":111},[87,8525,1190],{"class":97},[87,8527,8528],{"class":111},"!",[87,8530,8531],{"class":97},"fread.",[87,8533,4665],{"class":93},[87,8535,8536],{"class":97},"())\n",[87,8538,8539],{"class":89,"line":5761},[87,8540,1448],{"class":97},[87,8542,8543,8545,8547,8550,8552],{"class":89,"line":5792},[87,8544,3083],{"class":97},[87,8546,1214],{"class":111},[87,8548,8549],{"class":127}," \"打开文件失败，请确认文件名称是否正确！\"",[87,8551,4027],{"class":111},[87,8553,3097],{"class":97},[87,8555,8556,8558,8561,8563],{"class":89,"line":5828},[87,8557,4814],{"class":111},[87,8559,8560],{"class":111}," -",[87,8562,1562],{"class":231},[87,8564,2211],{"class":97},[87,8566,8567],{"class":89,"line":5861},[87,8568,1480],{"class":97},[87,8570,8571],{"class":89,"line":5891},[87,8572,399],{"emptyLinePlaceholder":398},[87,8574,8575],{"class":89,"line":5922},[87,8576,8577],{"class":101},"    //读取文件中的数据\n",[87,8579,8580,8582],{"class":89,"line":5927},[87,8581,8285],{"class":111},[87,8583,8584],{"class":97}," xRead;\n",[87,8586,8587,8590,8593,8595,8597,8600],{"class":89,"line":5933},[87,8588,8589],{"class":97},"    fread[",[87,8591,8592],{"class":127},"\"x\"",[87,8594,1718],{"class":97},[87,8596,4390],{"class":111},[87,8598,8599],{"class":97}," xRead;",[87,8601,8602],{"class":101},"  //读取浮点型数据\n",[87,8604,8605,8607,8609,8612,8614,8617,8619],{"class":89,"line":6710},[87,8606,3238],{"class":97},[87,8608,1214],{"class":111},[87,8610,8611],{"class":127}," \"x=\"",[87,8613,4027],{"class":111},[87,8615,8616],{"class":97}," xRead ",[87,8618,1214],{"class":111},[87,8620,3097],{"class":97},[87,8622,8623],{"class":89,"line":6724},[87,8624,399],{"emptyLinePlaceholder":398},[87,8626,8627],{"class":89,"line":6763},[87,8628,8629],{"class":101},"    //读取字符串数据\n",[87,8631,8632],{"class":89,"line":6779},[87,8633,8634],{"class":97},"    string strRead;\n",[87,8636,8637,8639,8642,8644,8646],{"class":89,"line":6796},[87,8638,8589],{"class":97},[87,8640,8641],{"class":127},"\"str\"",[87,8643,1718],{"class":97},[87,8645,4390],{"class":111},[87,8647,8648],{"class":97}," strRead;\n",[87,8650,8651,8653,8655,8658,8660,8663,8665],{"class":89,"line":6819},[87,8652,3238],{"class":97},[87,8654,1214],{"class":111},[87,8656,8657],{"class":127}," \"str=\"",[87,8659,4027],{"class":111},[87,8661,8662],{"class":97}," strRead ",[87,8664,1214],{"class":111},[87,8666,3097],{"class":97},[87,8668,8669],{"class":89,"line":6831},[87,8670,399],{"emptyLinePlaceholder":398},[87,8672,8673],{"class":89,"line":6836},[87,8674,8675],{"class":101},"    //读取含多个数据的number_array节点\n",[87,8677,8678,8681,8683,8686,8689],{"class":89,"line":6857},[87,8679,8680],{"class":97},"    FileNode fileNode ",[87,8682,112],{"class":111},[87,8684,8685],{"class":97}," fread[",[87,8687,8688],{"class":127},"\"number_array\"",[87,8690,2867],{"class":97},[87,8692,8693,8695,8697,8700],{"class":89,"line":6862},[87,8694,3238],{"class":97},[87,8696,1214],{"class":111},[87,8698,8699],{"class":127}," \"number_array=[\"",[87,8701,2211],{"class":97},[87,8703,8704],{"class":89,"line":6874},[87,8705,8706],{"class":101},"    //循环遍历每个数据\n",[87,8708,8709,8711,8714,8716,8719,8722,8725,8727,8729,8732,8735,8737],{"class":89,"line":6879},[87,8710,1416],{"class":111},[87,8712,8713],{"class":97}," (FileNodeIterator i ",[87,8715,112],{"class":111},[87,8717,8718],{"class":97}," fileNode.",[87,8720,8721],{"class":93},"begin",[87,8723,8724],{"class":97},"(); i ",[87,8726,3222],{"class":111},[87,8728,8718],{"class":97},[87,8730,8731],{"class":93},"end",[87,8733,8734],{"class":97},"(); i",[87,8736,1400],{"class":111},[87,8738,3010],{"class":97},[87,8740,8741],{"class":89,"line":6884},[87,8742,1448],{"class":97},[87,8744,8745,8748],{"class":89,"line":6889},[87,8746,8747],{"class":111},"        float",[87,8749,2193],{"class":97},[87,8751,8752,8755,8757,8759],{"class":89,"line":6901},[87,8753,8754],{"class":111},"        *",[87,8756,2217],{"class":97},[87,8758,4390],{"class":111},[87,8760,2193],{"class":97},[87,8762,8763,8765,8767,8769,8771,8774],{"class":89,"line":6910},[87,8764,3083],{"class":97},[87,8766,1214],{"class":111},[87,8768,373],{"class":97},[87,8770,1214],{"class":111},[87,8772,8773],{"class":127},"\" \"",[87,8775,2211],{"class":97},[87,8777,8778],{"class":89,"line":6915},[87,8779,1480],{"class":97},[87,8781,8782,8784,8786,8788,8790],{"class":89,"line":6920},[87,8783,3238],{"class":97},[87,8785,1214],{"class":111},[87,8787,8377],{"class":127},[87,8789,4027],{"class":111},[87,8791,3097],{"class":97},[87,8793,8794],{"class":89,"line":6931},[87,8795,399],{"emptyLinePlaceholder":398},[87,8797,8798],{"class":89,"line":6936},[87,8799,8800],{"class":101},"    //读取Mat类型数据\n",[87,8802,8803],{"class":89,"line":6958},[87,8804,8805],{"class":97},"    Mat matRead;\n",[87,8807,8808,8810,8813,8815,8817],{"class":89,"line":6963},[87,8809,8589],{"class":97},[87,8811,8812],{"class":127},"\"mat=\"",[87,8814,1718],{"class":97},[87,8816,4390],{"class":111},[87,8818,8819],{"class":97}," matRead;\n",[87,8821,8822,8824,8826,8829,8831,8834,8836],{"class":89,"line":6976},[87,8823,3238],{"class":97},[87,8825,1214],{"class":111},[87,8827,8828],{"class":127}," \"mat=\"",[87,8830,4027],{"class":111},[87,8832,8833],{"class":97}," mat ",[87,8835,1214],{"class":111},[87,8837,3097],{"class":97},[87,8839,8840],{"class":89,"line":6984},[87,8841,399],{"emptyLinePlaceholder":398},[87,8843,8844],{"class":89,"line":6989},[87,8845,8846],{"class":101},"    //读取含有多个子节点的节点数据，不使用FileNode和迭代器进行读取\n",[87,8848,8849,8852,8854,8856,8859],{"class":89,"line":7003},[87,8850,8851],{"class":97},"    FileNode fileNode1 ",[87,8853,112],{"class":111},[87,8855,8685],{"class":97},[87,8857,8858],{"class":127},"\"multi_nodes\"",[87,8860,2867],{"class":97},[87,8862,8863,8865,8868,8870,8872,8874,8877,8880],{"class":89,"line":7019},[87,8864,6727],{"class":111},[87,8866,8867],{"class":97}," month ",[87,8869,112],{"class":111},[87,8871,1190],{"class":97},[87,8873,28],{"class":111},[87,8875,8876],{"class":97},")fileNode1[",[87,8878,8879],{"class":127},"\"month\"",[87,8881,2867],{"class":97},[87,8883,8884,8886,8889,8891,8893,8895,8897,8900],{"class":89,"line":7035},[87,8885,6727],{"class":111},[87,8887,8888],{"class":97}," day ",[87,8890,112],{"class":111},[87,8892,1190],{"class":97},[87,8894,28],{"class":111},[87,8896,8876],{"class":97},[87,8898,8899],{"class":127},"\"day\"",[87,8901,2867],{"class":97},[87,8903,8904,8906,8909,8911,8913,8915,8917,8920],{"class":89,"line":7071},[87,8905,6727],{"class":111},[87,8907,8908],{"class":97}," year ",[87,8910,112],{"class":111},[87,8912,1190],{"class":97},[87,8914,28],{"class":111},[87,8916,8876],{"class":97},[87,8918,8919],{"class":127},"\"year\"",[87,8921,2867],{"class":97},[87,8923,8924,8926,8928,8931,8933],{"class":89,"line":7089},[87,8925,3238],{"class":97},[87,8927,1214],{"class":111},[87,8929,8930],{"class":127}," \"multi_nodes:\"",[87,8932,4027],{"class":111},[87,8934,8935],{"class":97}," endl \n",[87,8937,8938,8940,8943,8945,8947,8949,8952,8954,8956,8958,8961,8963],{"class":89,"line":7094},[87,8939,8428],{"class":111},[87,8941,8942],{"class":127}," \"  month=\"",[87,8944,4027],{"class":111},[87,8946,8867],{"class":97},[87,8948,1214],{"class":111},[87,8950,8951],{"class":127}," \"  day=\"",[87,8953,4027],{"class":111},[87,8955,8888],{"class":97},[87,8957,1214],{"class":111},[87,8959,8960],{"class":127}," \"  year=\"",[87,8962,4027],{"class":111},[87,8964,8965],{"class":97}," year;\n",[87,8967,8968,8970,8972,8975],{"class":89,"line":7101},[87,8969,3238],{"class":97},[87,8971,1214],{"class":111},[87,8973,8974],{"class":127}," \"  time=[\"",[87,8976,2211],{"class":97},[87,8978,8979,8981,8983,8985,8987,8989,8991,8993,8995,8997,9000,9002],{"class":89,"line":7106},[87,8980,1416],{"class":111},[87,8982,1190],{"class":97},[87,8984,28],{"class":111},[87,8986,1384],{"class":97},[87,8988,112],{"class":111},[87,8990,1389],{"class":231},[87,8992,1392],{"class":97},[87,8994,222],{"class":111},[87,8996,5647],{"class":231},[87,8998,8999],{"class":97},"; i",[87,9001,1400],{"class":111},[87,9003,3010],{"class":97},[87,9005,9006],{"class":89,"line":7111},[87,9007,1448],{"class":97},[87,9009,9010,9013,9015,9017,9019,9021,9023,9026],{"class":89,"line":7122},[87,9011,9012],{"class":111},"        int",[87,9014,2157],{"class":97},[87,9016,112],{"class":111},[87,9018,1190],{"class":97},[87,9020,28],{"class":111},[87,9022,8876],{"class":97},[87,9024,9025],{"class":127},"\"time\"",[87,9027,9028],{"class":97},"][i];\n",[87,9030,9031,9033,9035,9037,9039,9041],{"class":89,"line":7131},[87,9032,3083],{"class":97},[87,9034,1214],{"class":111},[87,9036,2157],{"class":97},[87,9038,1214],{"class":111},[87,9040,3257],{"class":127},[87,9042,2211],{"class":97},[87,9044,9045],{"class":89,"line":7140},[87,9046,1480],{"class":97},[87,9048,9050,9052,9054,9056,9058],{"class":89,"line":9049},83,[87,9051,3238],{"class":97},[87,9053,1214],{"class":111},[87,9055,8377],{"class":127},[87,9057,4027],{"class":111},[87,9059,3097],{"class":97},[87,9061,9063],{"class":89,"line":9062},84,[87,9064,6407],{"class":97},[87,9066,9068],{"class":89,"line":9067},85,[87,9069,8477],{"class":101},[87,9071,9073,9076,9078],{"class":89,"line":9072},86,[87,9074,9075],{"class":97},"    fread.",[87,9077,7117],{"class":93},[87,9079,519],{"class":97},[87,9081,9083,9085,9087],{"class":89,"line":9082},87,[87,9084,5594],{"class":111},[87,9086,1389],{"class":231},[87,9088,2211],{"class":97},[87,9090,9092],{"class":89,"line":9091},88,[87,9093,1486],{"class":97},[10,9095,9096,9097],{},"Figure 2-9 XML and YAML files generated by the myXMLandYAML.cpp program\n",[37,9098],{"alt":39,"src":9099},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776174565386.webp",[10,9101,9102,9103],{},"Figure 2-10 Reading results of the myXMLandYAML.cpp program file\n",[37,9104],{"alt":39,"src":9105},"https://cdn.tungchiahui.cn/tungwebsite/assets/images/2026/04/13/1776174573509.webp",[14,9107,9109],{"id":9108},"chapter-summary","## Chapter Summary",[10,9111,9112],{},"In this chapter, we first introduced how to use the Mat class in OpenCV 4 for storing image data, then covered image reading and display, video loading and camera access, and finally discussed how to save images, video files, as well as how to save and read XML and YAML files.",[10,9114,9115],{},"Here is the list of main functions in this chapter.",[253,9117,9118,9131],{},[256,9119,9120],{},[259,9121,9122,9125,9128],{},[262,9123,9124],{"align":2459},"Function name",[262,9126,9127],{"align":2459},"Function Description",[262,9129,9130],{"align":2459},"Code Listing",[272,9132,9133,9145,9158,9170,9182,9194,9207],{},[259,9134,9135,9139,9142],{},[277,9136,9137],{"align":2459},[22,9138,3417],{},[277,9140,9141],{"align":2459},"Read the image file",[277,9143,9144],{"align":2459},"2-24",[259,9146,9147,9152,9155],{},[277,9148,9149],{"align":2459},[22,9150,9151],{},"namedWindow()",[277,9153,9154],{"align":2459},"Create a window to display an image.",[277,9156,9157],{"align":2459},"2-25",[259,9159,9160,9164,9167],{},[277,9161,9162],{"align":2459},[22,9163,3804],{},[277,9165,9166],{"align":2459},"Display an image in a specified window",[277,9168,9169],{"align":2459},"2-26",[259,9171,9172,9176,9179],{},[277,9173,9174],{"align":2459},[22,9175,6057],{},[277,9177,9178],{"align":2459},"Call the camera or read/save video files",[277,9180,9181],{"align":2459},"2-27",[259,9183,9184,9188,9191],{},[277,9185,9186],{"align":2459},[22,9187,5114],{},[277,9189,9190],{"align":2459},"Save the image to a file.",[277,9192,9193],{"align":2459},"2-30",[259,9195,9196,9201,9204],{},[277,9197,9198],{"align":2459},[22,9199,9200],{},"VideoWriter()",[277,9202,9203],{"align":2459},"Save multiple frames of images as a video file.",[277,9205,9206],{"align":2459},"2-33",[259,9208,9209,9214,9217],{},[277,9210,9211],{"align":2459},[22,9212,9213],{},"FileStorage()",[277,9215,9216],{"align":2459},"Read or save XML, YAML files",[277,9218,9219],{"align":2459},"2-35",[9221,9222,9223],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":83,"searchDepth":105,"depth":105,"links":9225},[9226,9227,9228,9229,9230],{"id":16,"depth":137,"text":17},{"id":3401,"depth":137,"text":3402},{"id":4265,"depth":137,"text":4266},{"id":5100,"depth":137,"text":5101},{"id":9108,"depth":137,"text":9109},"/en-us/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun",2000000,"2026-04-13","wiki/2026-04-13-opencv-jiao-cheng","en-us:2026-04-13-opencv-jiao-cheng","/en-us/wiki/2026-04-13-opencv-jiao-cheng","OpenCV教程","md","wiki/2026-04-13-OpenCV教程/ch2-数据载入、显示与保存",false,null,"en-US","en-us",{},{"title":5,"description":12},"/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun","_i18n/en-us/wiki/2026-04-13-OpenCV教程/ch2-数据载入、显示与保存","I_lUUgsSIcyDVcqeCJ3DZVe4RRT6d-vsi9haIJdncxg",[9250,9255,9256,9261],{"path":9251,"stem":9252,"title":9253,"date":9233,"chapter":1562,"chapterSort":9254,"docKey":9235,"docRoot":9236,"docTitle":9237,"isWikiDoc":398,"isWikiIndex":9240},"/en-us/wiki/2026-04-13-opencv-jiao-cheng/ch1-chu-shi-opencv","_i18n/en-us/wiki/2026-04-13-OpenCV教程/ch1-初识OpenCV","Getting Started with OpenCV",1000000,{"path":9231,"stem":9247,"title":5,"date":9233,"chapter":871,"chapterSort":9232,"docKey":9235,"docRoot":9236,"docTitle":9237,"isWikiDoc":398,"isWikiIndex":9240},{"path":9257,"stem":9258,"title":9259,"date":9233,"chapter":232,"chapterSort":9260,"docKey":9235,"docRoot":9236,"docTitle":9237,"isWikiDoc":398,"isWikiIndex":9240},"/en-us/wiki/2026-04-13-opencv-jiao-cheng/ch3-tu-xiang-ji-ben-cao-zuo","_i18n/en-us/wiki/2026-04-13-OpenCV教程/ch3-图像基本操作","Basic Image Operations",3000000,{"path":9236,"stem":9262,"title":9263,"date":9233,"chapter":9241,"chapterSort":9264,"docKey":9235,"docRoot":9236,"docTitle":9237,"isWikiDoc":398,"isWikiIndex":398},"_i18n/en-us/wiki/2026-04-13-OpenCV教程/index","OpenCV tutorial",0,{"variants":9266},[9267,9268,9271,9274,9277],{"path":9231,"localeSlug":9243,"i18nKey":9239},{"path":9269,"localeSlug":9270,"i18nKey":9239},"/zh-hant/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun","zh-hant",{"path":9272,"localeSlug":9273,"i18nKey":9239},"/zh-hk/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun","zh-hk",{"path":9275,"localeSlug":9276,"i18nKey":9239},"/zh-tw/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun","zh-tw",{"path":9278,"localeSlug":9279,"i18nKey":9239},"/zh-cn/wiki/2026-04-13-opencv-jiao-cheng/ch2-shu-ju-zai-ru-xian-shi-yu-bao-cun","zh-cn",[9231,9246,9269,9246,9272,9246,9275,9246,9278,9246],1780663019970]