基于改进YOLO算法的夜间车辆检测

目前开源的车辆检测模型主要是针对白天场景,夜晚的车辆检测基本找不到。由于项目需要,只好自己训练了一个基于YOLO的夜间车辆检测模型。

采用的网络结构car.cfg:

[net]
# Testing
#batch=1
#subdivisions=1
# Training
batch=64
subdivisions=4
width=512
height=512
channels=3
momentum=0.9
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1

learning_rate=0.001
burn_in=1000
max_batches = 5000
policy=steps
steps=3800,4500
scales=.1,.1

[convolutional]
batch_normalize=1
filters=16
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=32
size=3
stride=2
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=32
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=64
size=3
stride=2
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=64
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=128
size=3
stride=2
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=256
size=3
stride=2
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=2
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

#########################
### SPP ###
[maxpool]
stride=1
size=5

[route]
layers=-2

[maxpool]
stride=1
size=9

[route]
layers=-4

[maxpool]
stride=1
size=13

[route]
layers=-1,-3,-5,-6

### End SPP ###

#########################
[convolutional]
batch_normalize=1
filters=256
size=1
stride=1
pad=1
activation=leaky

[convolutional]
batch_normalize=1
filters=512
size=3
stride=1
pad=1
activation=leaky

[convolutional]
size=1
stride=1
pad=1
filters=21
activation=linear

[yolo]
mask = 6,7,8
anchors = 16, 21,  21, 28,  27, 37,  34, 49,  42, 67,  58, 84,  64,112,  85,131, 128,242
classes=2
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1
scale_x_y = 1.05
iou_thresh=0.213
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
nms_kind=greedynms
beta_nms=0.6
max_delta=5

[route]
layers = -4

[convolutional]
batch_normalize=1
filters=128
size=1
stride=1
pad=1
activation=leaky

[upsample]
stride=2

[route]
layers = -1, 8

[convolutional]
batch_normalize=1
filters=256
size=3
stride=1
pad=1
activation=leaky

[convolutional]
size=1
stride=1
pad=1
filters=21
activation=linear

[yolo]
mask = 3,4,5
anchors = 16, 21,  21, 28,  27, 37,  34, 49,  42, 67,  58, 84,  64,112,  85,131, 128,242
classes=2
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1
scale_x_y = 1.05
iou_thresh=0.213
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
nms_kind=greedynms
beta_nms=0.6
max_delta=5

[route]
layers = -4

[convolutional]
batch_normalize=1
filters=64
size=1
stride=1
pad=1
activation=leaky

[upsample]
stride=2

[route]
layers = -1, 6

[convolutional]
batch_normalize=1
filters=128
size=3
stride=1
pad=1
activation=leaky

[convolutional]
size=1
stride=1
pad=1
filters=21
activation=linear

[yolo]
mask = 0,1,2
anchors = 16, 21,  21, 28,  27, 37,  34, 49,  42, 67,  58, 84,  64,112,  85,131, 128,242
classes=2
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
random=1
scale_x_y = 1.05
iou_thresh=0.213
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
nms_kind=greedynms
beta_nms=0.6
max_delta=5

训练之后,模型的测试效果还行

#include "stdafx.h"
#include 
#include 
#include 
#include 
#include 
using namespace cv;
using namespace dnn;
using namespace std;
float confThreshold = (float) 0.50;
float nmsThreshold = (float) 0.50;
vector classes;
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame);
/*************************************************
函数名:
函数描述:
输入参数:
输出参数:
返回值:
**************************************************/
vector getOutputsNames(const dnn::Net& net)
{
	static vector names;
	if (names.empty())
	{
		vector outLayers = net.getUnconnectedOutLayers();
		vector layersNames = net.getLayerNames();
		names.resize(outLayers.size());
		for (size_t i = 0; i < outLayers.size(); ++i)
			names[i] = layersNames[outLayers[i] - 1];
	}
	return names;
}
/*************************************************
函数名:
函数描述:
输入参数:
输出参数:
返回值:
**************************************************/
void postprocess(Mat& frame, vector& outs)
{
	vector classIds;
	vector confidences;
	vector boxes;
	for (size_t i = 0; i < outs.size(); ++i)
	{
		float* data = (float*)outs[i].data;
		for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols)
		{
			Mat scores = outs[i].row(j).colRange(5, outs[i].cols);
			Point classIdPoint;
			double confidence;
			minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);
			int centerX = (int)(data[0] * frame.cols);
			int centerY = (int)(data[1] * frame.rows);
			int width = (int)(data[2] * frame.cols);
			int height = (int)(data[3] * frame.rows);
			int left = centerX - width / 2;
			int top = centerY - height / 2;
			classIds.push_back(classIdPoint.x);
			confidences.push_back((float)confidence);
			boxes.push_back(Rect(left, top, width, height));
		}
	}
	vector indices;
	dnn::NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);
	for (size_t i = 0; i < indices.size(); ++i)
	{
		int idx = indices[i];
		Rect box = boxes[idx];
		drawPred(classIds[idx], confidences[idx], box.x, box.y,
			box.x + box.width, box.y + box.height, frame);
	}
}
/*************************************************
函数名:
函数描述:
输入参数:
输出参数:
返回值:
**************************************************/
void drawPred(int classId, float conf, int left, int top, int right, int bottom, Mat& frame)
{
	//标签值初始化为置信度
	string label = format("%.2f", conf);
	if (classId == 0) {
		rectangle(frame, Point(left, top), Point(right, bottom), Scalar(0, 255, 0), 2);
		putText(frame, label, Point(right + 10, top + 40), FONT_HERSHEY_COMPLEX, 0.4, Scalar(0, 255, 0), 1, 0);
	}//车头
	else {
		rectangle(frame, Point(left, top), Point(right, bottom), Scalar(255, 255, 0), 2);
		putText(frame, label, Point(right + 10, top + 40), FONT_HERSHEY_COMPLEX, 0.4, Scalar(255, 255, 0), 1, 0);
	}//车尾
}
/*************************************************
函数名:
函数描述:
输入参数:
输出参数:
返回值:
**************************************************/
int main()
{
	clock_t startTime, endTime;

	String modelConfiguration = "./model/car.cfg";
	String modelBinary = "./model/car.weights";
	Net net = readNetFromDarknet(modelConfiguration, modelBinary);
	if (net.empty())
	{
		printf("Could not load net...\n");
		return 0;
	}
	int i = 1000;//测试图片数量
	int j = 0;
	string path;
	Mat frame;
	cvNamedWindow("image", 0);
	resizeWindow("image", 1400, 800);
	while (j < i)
	{
		startTime = clock();
		// 加载图像
		path = "./valid/" + to_string(j) + ".jpg";
		startTime = clock();
		frame = imread(path);
		if (frame.empty()) {
			j++;
			continue;
		}
		Mat blob;
		dnn::blobFromImage(frame, blob, 1 / 255.0, Size(512, 512), Scalar(0, 0, 0), true, false);
		net.setInput(blob);
		vector outs;
		net.forward(outs, getOutputsNames(net));
		postprocess(frame, outs);//获取最后一层输出;
		Mat detectedFrame;
		frame.convertTo(detectedFrame, CV_8U);
		imshow("image", detectedFrame);
		endTime = clock();
		cout << "Totle Time : " << (double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << endl;
		waitKey();
		j++;
	}
	destroyWindow("image");
	return 0;
}

实际测试效果

基于改进YOLO算法的夜间车辆检测_第1张图片

你可能感兴趣的:(opencv,YOLO)