我彻底搜查过,并没有找到一个直截了当的答案.
将opencv matrices(cv::Mat)作为函数的参数传递,我们传递一个智能指针.我们对函数内部的输入矩阵所做的任何更改也会改变函数范围之外的矩阵.
我通过传递一个矩阵作为const引用来读取它,它不会在函数内被改变.但是一个简单的例子表明它确实:
void sillyFunc(const cv::Mat& Input, cv::Mat& Output){
Output = Input;
Output += 1;
}
int main( int argc, char** argv ){
cv::Mat A = cv::Mat::ones(3,3,CV_8U);
std::cout<<"A = \n"<<A<<"\n\n";
cv::Mat B;
sillyFunc(A,B);
std::cout<<"A = \n"<<A<<"\n\n";
std::cout<<"B = \n"<<B<<"\n\n";
}
Run Code Online (Sandbox Code Playgroud)
很明显,A即使它是作为一个发送,也会被改变const cv::Mat&.
这并不让我感到惊讶,因为在函数内部I2是一个简单I1的智能指针副本,因此任何改变I2都会改变I1.
什么是难不倒我的是,我不明白发送之间存在什么实际区别cv::Mat,const cv::Mat,const cv::Mat&或cv::Mat&作为参数的函数.
我知道如何覆盖这个(替换Output = Input;为Output = Input.clone();将解决问题)但仍然不明白上述差异.
多谢你们!
我在openCV中编写了一些代码,想要找到一个非常大的矩阵数组的中值(单通道灰度,浮点数).
我尝试了几种方法,例如对数组进行排序(使用std :: sort)并选择中间条目,但在与matlab中的中位函数进行比较时,它非常慢.确切地说 - 在matlab中需要0.25秒才能在openCV中花费超过19秒.
我的输入图像最初是尺寸为3840x2748(~1050万像素)的12位灰度图像,转换为浮点数(CV_32FC1),其中所有值现在都映射到范围[0,1]并且在代码I的某个点上通过调用请求中值:
double myMedianValue = medianMat(Input);
函数medianMat的位置是:
double medianMat(cv::Mat Input){
Input = Input.reshape(0,1); // spread Input Mat to single row
std::vector<double> vecFromMat;
Input.copyTo(vecFromMat); // Copy Input Mat to vector vecFromMat
std::sort( vecFromMat.begin(), vecFromMat.end() ); // sort vecFromMat
if (vecFromMat.size()%2==0) {return (vecFromMat[vecFromMat.size()/2-1]+vecFromMat[vecFromMat.size()/2])/2;} // in case of even-numbered matrix
return vecFromMat[(vecFromMat.size()-1)/2]; // odd-number of elements in matrix
}
Run Code Online (Sandbox Code Playgroud)
我把功能medinaMat本身和各个部分定时 - 正如预期的瓶颈在于:
std::sort( vecFromMat.begin(), vecFromMat.end() ); // sort vecFromMat
Run Code Online (Sandbox Code Playgroud)
这里有人有一个有效的解决方案吗?
谢谢!
编辑 我尝试使用Adi Shavit答案中给出的std :: nth_element.
函数medianMat现在读作:
double …Run Code Online (Sandbox Code Playgroud) 我搜索过互联网并没有找到解决方案.我希望这个问题不会重复.
我在同一个文件夹中有以下文件:
内文RUN_FILE.bat:
ffmpeg -i "IN.mp4" -c:v libx264 -crf 24 -c:a libmp3lame -aq 2 OUT.mp4
Run Code Online (Sandbox Code Playgroud)
内文RUN_AVS.bat:
ffmpeg -i "SCRIPT.avs" -c:v libx264 -crf 24 -c:a libmp3lame -aq 2 OUT.mp4
Run Code Online (Sandbox Code Playgroud)
SCRIPT.avs(3行)内的文字:
LoadPlugin("D:\MSharpen.dll")
DirectShowSource("D:\IN.MP4")
MSharpen(15,150)
Run Code Online (Sandbox Code Playgroud)
如果我尝试使用外部程序(如媒体播放器classic)加载avisynth脚本,它可以正常工作(并锐化视频帧).
转到命令行并运行RUN_FILE.bat按预期工作,但运行时RUN_AVS.bat我收到以下错误(请参见屏幕截图):

我发现这个令人困惑,因为配置了ffmpeg --enable-avisynth.
我很感激这方面的帮助 - 这是一个更大且非常重要的项目的一部分(自动扫描包含数百个视频文件的文件夹,锐化并将它们重新编码到具有相同文件名的另一个文件夹).
在Matlab中,通过组合霍夫变换,houghpeaks和houghlines,可以在原始图像中显示检测到的线条.
这可以在下面的图像中显示(通过使用来自Matlab的houghlines帮助的示例代码生成).检测到绿线.蓝色的是最长的一个:

我在我生成的简单合成图像上运行了cv :: HoughLines(几个正方形等).图像附在此处:

相关代码部分是:
cv::vector<cv::Vec2f> lines;
cv::HoughLines(I_BW, lines, 1, CV_PI/180,200);
cv::Mat linesMat ( lines, true );
Run Code Online (Sandbox Code Playgroud)
查看linesMat矩阵(我将其转换为此形式以便我可以使用图像监视来查看数据),同时运行for循环以在边缘图像上添加红线我看到rho和theta按最长的顺序排序图像中的线条.
我的输出是:

线条是图像的整个宽度(或高度).如何在Matlab示例中显示实际的行?我可以从rho + theta回到x和y,然后我必须以某种方式将它们链接到检测到的边缘等等 - 也许有一种简单的方法可以做到这一点,我错过了?
谢谢!