OpenCV中blobFromImage函数详细解释

这篇具有很好参考价值的文章主要介绍了OpenCV中blobFromImage函数详细解释。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

OpenCV中blobFromImage函数详细解释

OpenCV 3.3之后的版本中,支持调用训练好的深度学习框架,其中有一些重要的函数,今天先总结一下blobFromImage函数的用法。

在进行深度学习或者图片分类时,blobFromImage主要是用来对图片进行预处理。包含两个主要过程:

整体像素值减去平均值**(mean)**
通过缩放系数**(scalefactor)**对图片像素值进行缩放
下面我们看一下这个函数的形式:

blobFromImage(InputArray image, 
			  double scalefactor=1.0, 
		      const Size& size = Size(),
			  const Scalar& mean = Scalar(), 
			  bool swapRB = false, 
			  bool crop = false,
			  int ddepth = CV_32F)

下面我对这些参数,给大家提供给一个简单的介绍:

blob = cv2.dnn.blobFromImage(image, scalefactor=1.0, size, mean, swapRB=True,crop=False,ddepth = CV_32F )

**image:**这个就是我们将要输入神经网络进行处理或者分类的图片。

mean:需要将图片整体减去的平均值,如果我们需要对RGB图片的三个通道分别减去不同的值,那么可以使用3组平均值,如果只使用一组,那么就默认对三个通道减去一样的值。减去平均值**(mean):为了消除同一场景下不同光照的图片,对我们最终的分类或者神经网络的影响,我们常常对图片的R、G、B**通道的像素求一个平均值,然后将每个像素值减去我们的平均值,这样就可以得到像素之间的相对值,就可以排除光照的影响。

scalefactor:当我们将图片减去平均值之后,还可以对剩下的像素值进行一定的尺度缩放,它的默认值是1,如果希望减去平均像素之后的值,全部缩小一半,那么可以将scalefactor设为1/2

**size:**这个参数是我们神经网络在训练的时候要求输入的图片尺寸。

swapRB:OpenCV中认为我们的图片通道顺序是BGR,但是我平均值假设的顺序是RGB,所以如果需要交换RG,那么就要使swapRB=true
crop,如果crop裁剪为真,则调整输入图像的大小,使调整大小后的一侧等于相应的尺寸,另一侧等于或大于。然后,从中心进行裁剪。如果“裁剪”为“假”,则直接调整大小而不进行裁剪并保留纵横比。

ddepth, 输出blob的深度,选则CV_32F or CV_8U。

cv2.dnn.blobFromImage函数返回的blob是我们输入图像进行随意从中心裁剪,减均值、缩放和通道交换的结果。cv2.dnn.blobFromImagescv2.dnn.blobFromImage不同在于,前者接受多张图像,后者接受一张图像。多张图像使用cv2.dnn.blobFromImages有更少的函数调用开销,你将能够更快批处理图像或帧。

2、blobFromImage函数输出
函数返回4D矩阵(没有定义行/列值,因此这些值为-1)。

Mat [ -1*-1*CV_32FC1, isCont=true, isSubmat=false, nativeObj=0xaa2fd0, dataAddr=0x18d93080 ]
对于返回值有疑问,参见opencv官方issues
https://github.com/opencv/opencv/issues/12520
https://github.com/opencv/opencv/issues/12520

3、forward函数原型
Mat cv::dnn::Net::forward(const String & outputName = String())

    这个函数只需要提供layer的name即可;函数返回一个Mat变量,返回值是指输入的layername首次出现的输出。默认输出整个网络的运行结果。

    还有其它三个重载,请参考:

OpenCV4.xDNN(一)_爱CV-CSDN博客
https://blog.csdn.net/qq_35054151/article/details/112487829
https://blog.csdn.net/WHU_Kevin_Lin/article/details/108953227
https://blog.csdn.net/WHU_Kevin_Lin/article/details/108953227

4、对于返回结果的处理

(1)目标识别示例

Mat blob = blobFromImage(image, 1, Size(), Scalar(104, 117, 123));
 
net.setInput(blob);
Mat detections = net.forward();
Mat detectionMat(detections.size[2], detections.size[3], CV_32F, detections.ptr<float>());
 
for (int i = 0; i < detectionMat.rows; i++)
{
    //自定义阈值
    if (detectionMat.at<float>(i, 2) >= 0.14)
    {
        int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * image.cols);
        int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * image.rows);
        int xRightTop = static_cast<int>(detectionMat.at<float>(i, 5) * image.cols);
        int yRightTop = static_cast<int>(detectionMat.at<float>(i, 6) * image.rows);
 
        Rect object((int)xLeftBottom, (int)yLeftBottom,
            (int)(xRightTop - xLeftBottom),
            (int)(yRightTop - yLeftBottom));
 
        rectangle(image, object, Scalar(0, 255, 0));
    }
}

(2)语义分割示例

Mat blob = OpenCvSharp.Dnn.CvDnn.BlobFromImage(frame, 1.0 / 255, new OpenCvSharp.Size(256, 256), new Scalar(), false, false);
net.SetInput(blob);
 
Stopwatch sw = new Stopwatch();
sw.Start();
Mat prob = net.Forward(/*outNames[0]*/);
sw.Stop();
Console.WriteLine($"Runtime:{sw.ElapsedMilliseconds} ms");
 
Mat p = prob.Reshape(1, prob.Size(2));
Mat res = new Mat(p.Size(), MatType.CV_8UC1, Scalar.All(255));
for(int h=0; h<p.Height; h++)
{
    for (int w = 0; w < p.Width; w++)
    {
        res.Set<byte>(h, w, (byte)(p.At<float>(h, w) * 100));
    }
}

(3)目标分类示例1

int main(int argc, char** argv) 
{
	Net net = readNetFromCaffe("C:/Users/xiaomao/Desktop/dnn/bvlc_googlenet.prototxt", "C:/Users/xiaomao/Desktop/dnn/bvlc_googlenet.caffemodel");
	Mat image = imread("C:/Users/xiaomao/Desktop/8.png");
	Mat inputBlob = blobFromImage(image, 1, Size(224, 224), Scalar(104, 117, 123));
	Mat prob;
	cv::TickMeter t;
	for (int i = 0; i < 10; i++)
	{
		CV_TRACE_REGION("forward");
		net.setInput(inputBlob, "data");        //set the network input
		t.start();
		prob = net.forward("prob");                          //compute output
		t.stop();
	}
	int classId;
	double classProb;
	getMaxClass(prob, &classId, &classProb);//find the best class
	std::vector<String> classNames = readClassNames();
 
	string text = classNames.at(classId) + to_string(classProb * 100);
	
	putText(image, text, Point(5, 25), FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2);
 
	std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl;
	std::cout << "Probability: " << classProb * 100 << "%" << std::endl;
	std::cout << "Time: " << (double)t.getTimeMilli() / t.getCounter() << " ms (average from " << t.getCounter() << " iterations)" << std::endl;
	
	imshow("Image", image);
	waitKey(0);
	//system("pause");
	return 0;
}

(4)目标分类示例2
Opencv学习笔记 DNN模块调用Tensorflow的mobilenet对象检测模型_bashendixie5的博客-CSDN博客

https://blog.csdn.net/bashendixie5/article/details/109705409文章来源地址https://www.toymoban.com/news/detail-478409.html

到了这里,关于OpenCV中blobFromImage函数详细解释的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • OPENCV 编译选项以及解释

    cmake编译以及模块介绍,后面遇到没有的会继续再补充 CMAKE_BUILD_TYPE:指定构建类型,如Debug、Release等。 CMAKE_INSTALL_PREFIX:指定安装目录。 BUILD_SHARED_LIBS:设置为ON时,构建共享库;设置为OFF时,构建静态库。 BUILD_WITH_STATIC_CTR:当为ON是,构建静态运行时库(MT/MTd),设置为

    2024年02月06日
    浏览(35)
  • SiLu激活函数解释

    在yolo v5中,我们使用了SiLu激活函数 首先,了解一下激活函数的作用: 激活函数在神经网络中起到了非常重要的作用。以下是激活函数的一些主要功能: 引入非线性:激活函数的主要目标是在模型中引入非线性。这是因为,如果没有激活函数,无论神经网络有多少层,它都

    2024年02月07日
    浏览(34)
  • realloc函数用法解释

    realloc函数是将数组扩容的一个函数 用法:指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。 具体工作方法: 假设有一个p指针指向一个数组空间,如下图所示 想在想要使这个数组的空间变为原来的2倍,realloc函数就会在p指向的这个数组空间后面申请一段

    2024年02月12日
    浏览(53)
  • matlab中repmat()函数解释

    repmat意思是 复制和平铺矩阵,何为平铺?举个简单例子   如上述结果可知,其将矩阵(0  1)复制以及向右向下平铺成一个以矩阵(0  1)为单位的33阶的矩阵。 故总结一般repmat函数有如下两种形式:                                             A=[1,2,3,4]  repmat(A,3)

    2024年02月11日
    浏览(33)
  • LLama的激活函数SwiGLU 解释

    目录 Swish激活函数 1. Swish函数公式 LLaMA模型中的激活函数 1. SwiGLU激活函数 2. SwiGLU激活函数的表达式 3. SwiGLU激活函数的优势 Swish激活函数 Swish是一种激活函数,其计算公式如下: 1. Swish函数公式 Swish(x) = x * sigmoid(x) 其中,sigmoid(x)是sigmoid函数,计算公式为: sigmoid(x) = 1 / (1 +

    2024年04月24日
    浏览(32)
  • typedef函数代码段解释以及部分Windows下的系统函数

    在 C/C++ 中,typedef 用于创建类型别名,它可以让你为一个已有的数据类型定义一个新的名称,从而使代码更加清晰、易读,也可以简化类型的声明和使用。 这段代码用 typedef 定义了一个函数指针类型 LPSDOLInitialize ,该函数指针指向一个函数,该函数接受一个指向 SDOLAppInfo 结

    2024年02月12日
    浏览(40)
  • npm 命令及其详细解释

    npm init 用途:用于初始化一个新的 Node.js 项目,并生成 package.json 文件。 详解:该命令会引导您填写项目的基本信息,如项目名称、版本、描述等,并创建 package.json 文件以保存这些信息。 npm install package 用途:用于安装指定的 Node.js 包。 详解:执行该命令将会下载并安装指

    2024年04月15日
    浏览(33)
  • 动态规划【DP】详细解释

    动态规划,英文简称DP,是一种常见的算法设计思想。 它通常被应用于需要求解最优化问题的场景中。其核心思想是将原问题分解成若干个子问题进行求解,并将子问题的解记录下来,避免重复计算。 动态规划的常见四步骤为:定义状态;设计状态转移方程;给定边界条件;

    2024年02月05日
    浏览(36)
  • Python: locals()详细解释

    locals() 是一个内置函数,用于返回当前局部作用域的字典。这个字典包含了当前函数或模块中所有局部变量的名称和值。具体来说: 返回值 :一个字典,包含了当前局部作用域的所有局部变量。 这个函数在不同的上下文中有不同的用途: 在这个例子中, local_vars 将包含函数

    2024年01月16日
    浏览(35)
  • Transformer详细解释

    transformer的细节到底是怎么样的?Transformer 连环18问! 4.1  从功能角度,Transformer Encoder的核心作用是提取特征,也有使用Transformer Decoder来提取特征。例如,一个人学习跳舞,Encoder是看别人是如何跳舞的,Decoder是将学习到的经验和记忆,展现出来 4.2  从结构角度,如图5所示

    2024年02月13日
    浏览(7)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包