[英]what is the fastest way to search inside a matrix for min and max alongside of different rows or cols in c++
假設我需要在行和列的矩陣內搜索以找到最小值,這是最好的方法嗎?
我現在能想到的是有兩個嵌套向量如下:
std::vector<std::vector<float>> myData;
並以這種方式搜索它:
// row search on row say 10
int index= std::min_element(myData[10].begin(), myData[10].end()) - myData[10].begin();
但是為了搜索cols,我需要寫一個for循環來進行搜索。
// col search say on col 20
float min_value=10000000; / assuming values in table are less than this value
int min_index=-1;
for(int i=0;i<myData.size();++i)
{
if(myData[i][20] <min_value)
{
min_value=myData[i][20];
min_index=i;
}
}
有沒有更好的方法來做到這一點? 我也可以訪問OpenCV。
如果您有OpenCV Mat,可以使用minMaxLoc :
void minMaxLoc(InputArray src, double* minVal, double* maxVal=0,
Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
返回值minVal/maxVal
包含實際值,而minLoc/maxLoc
是min / max的坐標(如果有多個,則為第一次出現)。
顯然,如果你傳遞整個矩陣,你將得到全局最小值/最大值,但你也可以只傳遞一行或一列。
對於矩陣C
您可以使用Mat :: col找到列n
的最小值/最大值
minMaxLoc(C.col(n), &minVal, &maxVal, &minLoc, &maxLoc);
或者對於使用Mat :: row的行m
minMaxLoc(C.row(m), &minVal, &maxVal, &minLoc, &maxLoc);
Mat::col
和Mat::row
都是O(1)
操作,因為它們不復制任何數據,但我沒有做任何基准來確定它們的列迭代速度。
我們可以使用cv::reduce
( 1 )作為行/列方式的最小值/最大值,而不是使用范圍/ roi的minMaxLoc
。 以下示例。
unsigned char data[4][2] = { 1,2,3,4,5,6,7,8 };
Mat img(4, 2, CV_8UC1, data) ;
Mat rowMinImg;
int singleCoumnResult = 1;
cv::reduce(img, rowMinImg, singleCoumnResult, CV_REDUCE_MIN );
//Mat colMinImg;
//int singleRowResult = 0;
//cv::reduce(img, colMinImg, singleRowResult, CV_REDUCE_MIN );
快速瀏覽一下cv :: reduce( 2 )的實現,可以看出它是一個簡單的for循環來查找min / max值。 所以,如果你的數據已經存在於OpenCV Mat
,我認為這是要走的路。
雖然這可能比您想要的更復雜,但可以繼承迭代器基類 。 那里有一個簡單的例子。 您將重新定義運算符以遍歷列。 這樣,您可以像行迭代器一樣將它們傳遞給min_element。
如果我理解正確,您希望能夠找到給定矩陣的最小值和最大值(和位置):
然后以下MWE可以幫助您。 我們先來看一下輸出:
mat =
[75, 97, 66, 95, 15, 22;
24, 21, 71, 72, 34, 66;
21, 69, 88, 72, 64, 1;
26, 47, 26, 40, 95, 24;
70, 37, 9, 83, 16, 83]
global min = 1 @ [5, 2]
global max = 97 @ [1, 0]
Row 0 min = 15 @ [4, 0] max = 97 @ [1, 0]
Row 1 min = 21 @ [1, 1] max = 72 @ [3, 1]
Row 2 min = 1 @ [5, 2] max = 88 @ [2, 2]
Row 3 min = 24 @ [5, 3] max = 95 @ [4, 3]
Row 4 min = 9 @ [2, 4] max = 83 @ [3, 4]
Col 0 min = 21 @ [0, 2] max = 75 @ [0, 0]
Col 1 min = 21 @ [1, 1] max = 97 @ [1, 0]
Col 2 min = 9 @ [2, 4] max = 88 @ [2, 2]
Col 3 min = 40 @ [3, 3] max = 95 @ [3, 0]
Col 4 min = 15 @ [4, 0] max = 95 @ [4, 3]
Col 5 min = 1 @ [5, 2] max = 83 @ [5, 4]
和相應的代碼(你說可以使用OpenCV):
#include <opencv2/core/core.hpp>
#include <algorithm>
#include <iostream>
#include <iomanip>
namespace {
template <typename T>
std::pair< cv::Point, cv::Point > findMinMaxLoc( cv::Mat_<T> & mat )
{
double ignored1, ignored2;
std::pair< cv::Point, cv::Point > mmloc;
cv::minMaxLoc( mat, &ignored1, &ignored2, &(mmloc.first), &(mmloc.second) );
return mmloc;
}
template <typename T>
std::pair< cv::Point, cv::Point > minMaxLocRow( cv::Mat_<T> & mat, int row )
{
cv::Rect roi( 0, row, mat.size().width, 1 );
cv::Mat_<T> matRow = mat( roi );
std::pair< cv::Point, cv::Point > mmloc = findMinMaxLoc( matRow );
mmloc.first.y = row;
mmloc.second.y = row;
return mmloc;
}
template <typename T>
std::pair< cv::Point, cv::Point > minMaxLocCol( cv::Mat_<T> & mat, int col )
{
cv::Rect roi( col, 0, 1, mat.size().height );
cv::Mat_<T> matCol = mat( roi );
std::pair< cv::Point, cv::Point > mmloc = findMinMaxLoc( matCol );
mmloc.first.x = col;
mmloc.second.x = col;
return mmloc;
}
} // namespace
int main( int argc, char ** argv )
{
// Generate a matrix filled with random data.
cv::Size size( 6, 5 );
cv::Mat1i mat( size ); // Or cv::Mat1b, cv::Mat3f, etc.
cv::RNG rng( cv::getCPUTickCount() );
rng.fill( mat, cv::RNG::UNIFORM, 0, 100 );
std::cout << "mat = " << std::endl << mat << std::endl << std::endl;
// Find the global minimum and maximum.
std::pair< cv::Point, cv::Point > mmloc = findMinMaxLoc( mat );
std::cout << "global min = " << std::setw( 3 ) << std::setfill( ' ' );
std::cout << mat( mmloc.first ) << " @ " << mmloc.first << std::endl;
std::cout << "global max = " << std::setw( 3 ) << std::setfill( ' ' );
std::cout << mat( mmloc.second ) << " @ " << mmloc.second << std::endl << std::endl;
// Row-wise extrema.
for ( int row = 0; row < size.height; ++row )
{
std::pair< cv::Point, cv::Point > mmloc = minMaxLocRow( mat, row );
std::cout << "Row " << row;
std::cout << " min = " << std::setw( 3 ) << std::setfill( ' ' );
std::cout << mat( mmloc.first ) << " @ " << mmloc.first;
std::cout << " max = " << std::setw( 3 ) << std::setfill( ' ' );
std::cout << mat( mmloc.second ) << " @ " << mmloc.second << std::endl;
}
std::cout << std::endl;
// Column-wise extrema.
for ( int col = 0; col < size.width; ++col )
{
std::pair< cv::Point, cv::Point > mmloc = minMaxLocCol( mat, col );
std::cout << "Col " << col;
std::cout << " min = " << std::setw( 3 ) << std::setfill( ' ' );
std::cout << mat( mmloc.first ) << " @ " << mmloc.first;
std::cout << " max = " << std::setw( 3 ) << std::setfill( ' ' );
std::cout << mat( mmloc.second ) << " @ " << mmloc.second << std::endl;
}
return 0;
}
也許我提出的解決方案不是最好的方式 (你明確要求的),但它很簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.