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,所以如果需要交换R和G,那么就要使swapRB=true
crop,如果crop裁剪为真,则调整输入图像的大小,使调整大小后的一侧等于相应的尺寸,另一侧等于或大于。然后,从中心进行裁剪。如果“裁剪”为“假”,则直接调整大小而不进行裁剪并保留纵横比。
ddepth, 输出blob的深度,选则CV_32F or CV_8U。
cv2.dnn.blobFromImage函数返回的blob是我们输入图像进行随意从中心裁剪,减均值、缩放和通道交换的结果。cv2.dnn.blobFromImages和cv2.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://www.toymoban.com/news/detail-478409.html
https://blog.csdn.net/bashendixie5/article/details/109705409文章来源地址https://www.toymoban.com/news/detail-478409.html
到了这里,关于OpenCV中blobFromImage函数详细解释的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!