Yolov 3 모델 프레임 워 크 darknet 연구 (4) cpu + opencv 4.0.1 에서 yolov 3 모델 을 직접 실행 합 니 다.

6413 단어 딥 러 닝
opencv 3.4.2 부터 yolov 3 모델 을 직접 실행 하여 이미지 인식 을 할 수 있 습 니 다.적어도 나 는 windows + opencv 4.0.1 과 Ubuntu 18.04 + opencv 3.4.3 에서 운행 하 는 것 은 문제 가 없다. 
배경
GPU 에서 데 이 터 를 훈련 시 키 고 GPU 에서 추 리 를 하 는 것 은 이미 일상적인 일이 다.그러나 현실 적 으로 GPU 가 잘 훈련 되 기 를 바 라 는 알고리즘 모델 이 서로 다른 cpu 플랫폼 에서 추 리 를 할 수 있 도록 요구 하 는 장면 이 많다. 예 를 들 어 ARM, intel cpu 등 이다.여기 서 intel cpu 를 예 로 들 어 두 가지 방식 을 소개 합 니 다.
1) darknet c 코드 를 다운로드 하여 lib 로 만 든 다음 lib 인 터 페 이 스 를 호출 하여 이미지 인식 을 한다.
2) opencv 3.43 이상 버 전 을 설치 한 후 API 를 호출 하여 이미지 인식
방법 2 장점 이 뚜렷 하 다.
a) 공식 darknet 은 Makefile 만 Liux 에서 컴 파일 하고 windows 플랫폼 의 컴 파일 은 스스로 해결 할 수 있 습 니 다.
b) 더 중요 한 것 은 opencv 는 intel cpu 에 대해 많은 명령 집합 을 최적화 시 켰 기 때문에 같은 yolo 3 의 알고리즘 모델 에 대해 추 리 를 해 야 한다. 방법 1 은 6s 정도 이 고 opencv 방식 은 600 ms 정도 밖 에 안 된다.
여기 서 한 가지 더 설명해 야 한다. 인터넷 에서 opencv API 로 추리 하 는 시간 은 220 ms 에 불과 하 다 고 발 표 했 지만 나의 실험 결 과 는 600 ms 에 달 했다. 대략 두 가지 이유 가 있다.
(1) 인터넷 상의 신경 망 크기 는 416 x 416 이다.  제 사 이 즈 는 608 x608 입 니 다.  대략 전 자 는 1.5x 1.5 = 2.25
 (2) CPU 가 다르다.인터넷 에 i7 6 핵 이 있어 야 돼 요.  내 것 은 i54 캐 시 만 있어 도 많이 부족 하 다.
이루어지다
1。 네트워크 프로필, 가중치, 인식 할 그림 과 형식 이름 을 포함 한 입력 매개 변 수 를 준비 하 십시오.
//         
String model_config = "xxx/yolov3_2019_01.cfg";
String model_weights = "xxx/yolov3-2019_01_final.weights";
String image_file = "xxx/img20190108_000544.jpg";

vector class_names = get_class_names("xxx/class_2019_01.names");

2。opencv API 로 네트워크 모델 불 러 오기
// Load the network
	Net net = readNetFromDarknet(model_config, model_weights);
	if (net.empty())
	{
		printf("loading network fails 
"); return 1; } net.setPreferableBackend(DNN_BACKEND_OPENCV); net.setPreferableTarget(DNN_TARGET_CPU);

3。그림 을 읽 고 blob 4 차원 장 량 을 변환 하 는 동시에 네트워크 모델 size 로 크기 를 조정 합 니 다.
// Create a 4D blob from a frame.
	Mat frame, blob;
	frame = imread(image_file);
	if (frame.empty())
	{
		printf("reading image fails 
"); return 1; } int newwork_width = 608; int newwork_height = 608; blobFromImage(frame, blob, 1 / 255.0, Size(newwork_width, newwork_height), Scalar(0, 0, 0), true, false);

4。blob 를 모델 에 주입 하고 전방 향 예측 (최 소모 시간 부분)
	//Sets the input to the network
	net.setInput(blob);

	// Runs the forward pass to get output of the output layers
	vector outs;
	net.forward(outs, getOutputsNames(net));

식 별 된 outs 는 3 개의 mat 형식 데이터 인 데 왜 3 입 니까?darknet 에 3 개의 yolo 검 측 출력 층 이 있 으 니까!이 3 개의 mat 득 shape 는 각각 (4 + 1 + 5) x19x19x 3, (4 + 1 + 5) x38x 38x 3 이다.  (4+1+5)x76x76x3   주: 내 모델 안에 클 라 스 수량 은 5
5。outs 에서 신뢰 도가 한도 값 보다 높 은 box 를 선택 한 다음 에 NMS 를 추가 로 걸 러 냅 니 다.
	// Remove the bounding boxes with low confidence
	postprocess(class_names, frame, outs);



//         

// Initialize the parameters
float confThreshold = 0.5; // Confidence threshold
float nmsThreshold = 0.4;  // Non-maximum suppression threshold

// Draw the predicted bounding box    
void drawPred(vectorclasses, int classId, float conf, int left, int top, int right, int bottom, Mat& frame)
{
	//Draw a rectangle displaying the bounding box     
	rectangle(frame, Point(left, top), Point(right, bottom), Scalar(0, 0, 255));

	//Get the label for the class name and its confidence
	string label = format("%.2f", conf);//         

	//       ,       
	if (!classes.empty())
	{
		CV_Assert(classId < (int)classes.size());
		label = classes[classId] + ":" + label;
	}

	//Display the label at the top of the bounding box
	int baseLine;
	Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);
	top = max(top, labelSize.height);

	//      
	putText(frame, label, Point(left, top), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 255, 255));
}

// Remove the bounding boxes with low confidence using non-maxima suppression
void postprocess(vectorclasses, Mat& frame, const vector& outs)
{
	vector classIds;
	vector confidences;
	vector boxes;

	for (size_t i = 0; i < outs.size(); ++i)
	{
		// Scan through all the bounding boxes output from the network and keep only the
		// ones with high confidence scores. Assign the box's class label as the class
		// with the highest score for the box.
		float* data = (float*)outs[i].data;

		for (int j = 0; j < outs[i].rows; ++j, data += outs[i].cols)
		{
			int a = outs[i].cols;//    +    +   +        =2+2+1+80
			int b = outs[i].rows;//    507

			Mat scores = outs[i].row(j).colRange(5, outs[i].cols);//             ,      80   ,       
			Point classIdPoint;
			double confidence;

			// Get the value and location of the maximum score
			minMaxLoc(scores, 0, &confidence, 0, &classIdPoint);//         
			if (confidence > confThreshold)//     
			{
				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));
			}
		}
	}
	// Perform non maximum suppression to eliminate redundant overlapping boxes with
	// lower confidences
	vector indices;
	NMSBoxes(boxes, confidences, confThreshold, nmsThreshold, indices);// 、   、     、        、  (  )
	for (size_t i = 0; i < indices.size(); ++i)
	{
		int idx = indices[i];//   
		Rect box = boxes[idx];//    (    )

		drawPred(classes, classIds[idx], confidences[idx], box.x, box.y,
			box.x + box.width, box.y + box.height, frame);
	}
}

// Get the names of the output layers
vector getOutputsNames(const Net& net)
{
	static vector names;

	if (names.empty())
	{
		//Get the indices of the output layers, i.e. the layers with unconnected outputs
		vector outLayers = net.getUnconnectedOutLayers();

		//get the names of all the layers in the network
		vector layersNames = net.getLayerNames();

		// Get the names of the output layers in names
		names.resize(outLayers.size());

		for (size_t i = 0; i < outLayers.size(); ++i)
			names[i] = layersNames[outLayers[i] - 1];
	}

	return names;
}

좋은 웹페이지 즐겨찾기