C++ 在矩阵中搜索c+中不同行或列旁边的最小值和最大值的最快方法是什么+;
假设我需要在矩阵中搜索行和列以找到最小值,那么最好的方法是什么 我现在能想到的是有两个嵌套向量,如下所示:C++ 在矩阵中搜索c+中不同行或列旁边的最小值和最大值的最快方法是什么+;,c++,algorithm,opencv,C++,Algorithm,Opencv,假设我需要在矩阵中搜索行和列以找到最小值,那么最好的方法是什么 我现在能想到的是有两个嵌套向量,如下所示: std::vector<std::vector<float>> myData; 但是对于在cols上搜索,我需要编写一个for循环来进行搜索 // col search say on col 20 float min_value=10000000; / assuming values in table are less than this value in
std::vector<std::vector<float>> myData;
但是对于在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;
}
}
//列搜索在列20上说
浮动最小值=10000000;/假设表中的值小于此值
int min_指数=-1;
对于(int i=0;i,由于您的结构元素将发生变化,您最好的选择是使用(又称芬威克树)实现范围最小查询()。我建议您为每行和每列保留一棵这样的树。如果您希望支持对原始矩阵的子矩阵的查询,也可以实现这样的树的树。我建议的解决方案需要O(N*M)
额外的内存,其中N和M是矩阵的维度。它还将支持查询和更新的复杂性O(log(N)+log(M))
虽然这可能比您希望的更复杂,但可以对进行子类化。这里有一个简单的示例。您可以重新定义运算符以遍历列。这样,您可以像行迭代器一样将其传递到min_元素。如果您有OpenCV Mat,则可以使用:
返回值minVal/maxVal
包含实际值,而minLoc/maxLoc
是最小/最大值的坐标(如果有多个值,则第一次出现)
显然,如果你传递整个矩阵,你会得到全局最小值/最大值,但你也可以只传递一行或一列
对于矩阵C
,您可以使用
或对于行m
,使用
Mat::col
和Mat::row
都是O(1)
操作,因为它们不复制任何数据,但我没有做任何基准测试来确定它们的列迭代有多快。如果我理解正确,您希望能够找到给定矩阵的最小值和最大值(以及位置):
全球
在一行中
一栏
那么以下内容可能会对您有所帮助。让我们首先看看输出:
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):
#包括
#包括
#包括
#包括
名称空间{
模板
std::pairfindMinMaxLoc(cv::Mat\ux&Mat)
{
双重忽略1,忽略2;
std::pairmmloc;
cv::minMaxLoc(mat,&ignored1,&ignored2,&mmloc.first,&mmloc.second));
返回mmloc;
}
模板
std::pairminMaxLocRow(cv::Mat_&Mat,int-row)
{
cv::Rect roi(0,行,mat.size().宽度,1);
cv::Mat_u-matRow=Mat(投资回报率);
std::pairmmloc=findMinMaxLoc(matRow);
mmloc.first.y=行;
mmloc.second.y=行;
返回mmloc;
}
模板
std::pairminMaxLocCol(cv::Mat_&Mat,int col)
{
cv::Rect roi(col、0、1、mat.size().高度);
cv::Mat_u-matCol=Mat(投资回报率);
std::pairmmloc=findMinMaxLoc(matCol);
mmloc.first.x=列;
mmloc.second.x=列;
返回mmloc;
}
}//名称空间
int main(int argc,字符**argv)
{
//生成一个充满随机数据的矩阵。
cv::大小(6,5);
cv::Mat1i mat(尺寸);//或cv::Mat1b、cv::Mat3f等。
cv::RNG RNG(cv::getcputiccount());
rng.填充(材料,cv::rng::均匀,0,100);
std::cout我们可以对行/列最小值/最大值使用cv::reduce
(),而不是对range/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()的实现,表明查找最小值/最大值是一个简单的for循环。因此,如果您的数据已经存在于OpenCVMat
中,我认为这是一种方法。您的矩阵是动态变化的还是静态的?当我要计算最小值时,大小是已知的,但在编译过程中,大小是未知的。最快的方法是分配将矩阵作为一个连续的向量,并按顺序迭代。如果在构造时大小是固定的,那就是要做的。@Alex这会给我全局最小值,但我需要每行或每列旁边的最小值。我的意思是,值是否会动态变化?是否有一个y解决方案使用cv::Mat并易于使用和修改实施?我不知道有这样的解决方案,我也从未使用过cv::MatThis给出整个矩阵的最小值/最大值,但我对特定行/列旁边的最小值/最大值感兴趣。对不起,我不理解您对“旁边”一词的用法在本文中。好的,在阅读了一些其他答案后,您可能正在查找给定行或列的最小/最大值。我将更新我的答案。
minMaxLoc(C.col(n), &minVal, &maxVal, &minLoc, &maxLoc);
minMaxLoc(C.row(m), &minVal, &maxVal, &minLoc, &maxLoc);
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]
#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;
}
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 );