日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV reshape函数需要注意的细节

發(fā)布時間:2024/4/15 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV reshape函数需要注意的细节 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

OpenCV reshape函數(shù)需要注意的細節(jié)

【尊重原創(chuàng),轉(zhuǎn)載請注明出處】https://blog.csdn.net/guyuealian/article/details/80252853

? ? 本人在使用OpenCV的reshape()函數(shù)時,曾經(jīng)碰到一個大坑,出現(xiàn)一個非常奇葩的問題,先把原始的代碼貼上:

#include <opencv2/opencv.hpp> #include "continuousCapture.h"using namespace cv; using namespace std;template<typename _Tp> cv::Mat convertVector2Mat(vector<_Tp> v, int cn, int rows) {cv::Mat mat = cv::Mat(v);//將vector變成一列的matcv::Mat dest = mat.reshape(cn, rows);cout << "內(nèi)部dest=\n" << dest << endl;return dest; }int main() {/* char ->CV_8SC* unsigned char,uchar ->CV_8UC* unsigned short int,ushort->CV_16UC* short int->CV_16SC* int ->CV_32SC* float ->CV_32FC* double->CV_64FC*///int arr[4][3] = { { 1, 1,1 },{ 2, 2,2 },{ 3, 3,3 },{ 4,4, 4 } }; uchar arr[12] = { 1, 1,1 ,2, 2,2, 3, 3,3 ,4,4, 4 };vector<uchar> v(arr, arr + 12);//將一維數(shù)組轉(zhuǎn)為vectorcv::Mat dest=convertVector2Mat<uchar>(v,1, 4);//將vector轉(zhuǎn)為Matcout << "外部dest=\n" << dest << endl;system("pause");waitKey();return 0; }

? ? ?上面的程序,聲明一個函數(shù)convertVector2Mat()實現(xiàn)將vector轉(zhuǎn)OpenCV的Mat類型,因此用到了reshape()函數(shù),剛看convertVector2Mat()函數(shù),你是很難發(fā)現(xiàn)問題,但運行結(jié)果,且出乎意外:

內(nèi)部dest= [ 1, 1, 1;2, 2, 2;3, 3, 3;4, 4, 4] 外部dest= [221, 221, 221;221, 221, 221;221, 221, 221;221, 221, 221]

? ? Why?什么情況,convertVector2Mat()函數(shù)里的dest和返回dest的結(jié)果為什么不一樣的??為什么在函數(shù)計算正確的值,返回結(jié)果后卻出現(xiàn)問題了。 這個坑,鄙人弄了好久,一開始以為是類型出現(xiàn)問題,于是統(tǒng)一所有數(shù)據(jù)的類型為uchar或者int類型;后來,我改為引用的方式獲得dest的值,然而....問題依舊存在!!!

? ?再后來,一條代碼一條代碼的審核,終于定位到reshape()函數(shù),百度搜索的reshape()函數(shù)的用法都是坑,沒有一個說清楚,后來還是到OpenCV官網(wǎng)查看最權威的解釋:https://docs.opencv.org/3.2.0/d3/d63/classcv_1_1Mat.html#a4eb96e3251417fa88b78e2abd6cfd7d8

Changes the shape and/or the number of channels of a 2D matrix without copying the data.

The method makes a new matrix header for *this elements. The new matrix may have a different size and/or different number of channels. Any combination is possible if:

  • No extra elements are included into the new matrix and no elements are excluded. Consequently, the product rows*cols*channels() must stay the same after the transformation.
  • No data is copied. That is, this is an O(1) operation. Consequently, if you change the number of rows, or the operation changes the indices of elements row in some other way, the matrix must be continuous. See?Mat::isContinuous?.

For example, if there is a set of 3D points stored as an STL vector, and you want to represent the points as a 3xN matrix, do the following:

std::vector<Point3f> vec;...Mat pointMat = Mat(vec). // convert vector to Mat, O(1) operation reshape(1). // make Nx3 1-channel matrix out of Nx1 3-channel. // Also, an O(1) operation t(); // finally, transpose the Nx3 matrix. // This involves copying all the elements Parameters
cnNew number of channels. If the parameter is 0, the number of channels remains the same.
rowsNew number of rows. If the parameter is 0, the number of rows remains the same.

? ? ?看到了吧,(1)由于reshape只是在邏輯上改變矩陣的行列數(shù)或者通道數(shù), 但不會進行任何的數(shù)據(jù)的復制操作,新矩陣中不包含額外元素,也不包含任何元素。 因此,轉(zhuǎn)換后rows*cols*channels()必須保持不變。(2)沒有數(shù)據(jù)被復制。 也就是說,這是一個O(1)操作。 因此,如果更改行數(shù),或者操作以其他方式更改元素行的索引,則矩陣必須是連續(xù)的。關于OpenCV連續(xù)性的使用方法可以參考本人博客:https://blog.csdn.net/guyuealian/article/details/78614662

? ? ?知道這個reshape()的實現(xiàn)機制,鄙人猜測出現(xiàn)這種問題的原因了,應該是convertVector2Mat()函數(shù)內(nèi)部創(chuàng)建的mat和dest變量本質(zhì)上是同一塊內(nèi)存空間的,而返回后就已經(jīng)被釋放掉。dest引用的數(shù)據(jù)是來自于mat,并沒有拷貝數(shù)據(jù),因此在mat沒有釋放的情況下是正常的,但引用的內(nèi)存就被釋放后就變成野數(shù)據(jù)。要想解決這個問題也簡單,返回時,clone一份即可。如:

#include <opencv2/opencv.hpp> #include "continuousCapture.h"using namespace cv; using namespace std;template<typename _Tp> cv::Mat convertVector2Mat(vector<_Tp> v, int cn, int rows) {cv::Mat mat = cv::Mat(v);//將vector變成一列的matcv::Mat dest = mat.reshape(cn, rows).clone();//clone一份再返回cout << "內(nèi)部dest=\n" << dest << endl;return dest; }int main() {/* char ->CV_8SC* unsigned char,uchar ->CV_8UC* unsigned short int,ushort->CV_16UC* short int->CV_16SC* int ->CV_32SC* float ->CV_32FC* double->CV_64FC*///int arr[4][3] = { { 1, 1,1 },{ 2, 2,2 },{ 3, 3,3 },{ 4,4, 4 } }; uchar arr[12] = { 1, 1,1 ,2, 2,2, 3, 3,3 ,4,4, 4 };vector<uchar> v(arr, arr + 12);//將一維數(shù)組轉(zhuǎn)為vectorcv::Mat dest;dest=convertVector2Mat<uchar>(v, 1, 4);//將vector轉(zhuǎn)為Matcout << "外部dest=\n" << dest << endl;system("pause");waitKey();return 0; }
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生

總結(jié)

以上是生活随笔為你收集整理的OpenCV reshape函数需要注意的细节的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。