python_opencv与c++ opencv的效率对比 | opencv 提取HSV直方图特征

开门见山-结论:c++整体效率要比python快上数十倍,最大的原因应该是c++的循环快

背景

之前一直是用python opencv完成一些图像处理任务的,这次期末大作业有41247张1280*720的图片,需要提取直方图特征值,用python 简章慢的要死,估计一下要跑30-50个小时,那完蛋了,作业肯定交不上去的,优化无果后,最终决定用c++ opencv重写整个程序,有点惊喜

以下代码的功能:
按照getDegree量化规则,提取每一张图片的量化特征向量,写入到文件中

//三个关键参数
int ProcNum = 8;   //进程或者线程数
int totalFileNum = 100;  //本次共有多少文件
int lastJpg = 6500;  //上一次已经读取的最后一个文件

以下是C++ 提取HSV直方图特征代码:

#include
#include 
#include
#include 
#include 
#include 
#include   
#include   
#include "Timer.h"

using namespace cv;
namespace {
	using std::cout ;
	using std::endl;
	std::string  SAMPLE_FOLDER = "E:\\work\\VS\\readjpg\\frameSet\\";
	std::string OUTPUT_FOLDER = "E:\\work\\VS\\readjpg\\output\\";
	//忽略了V这一层的影响
	int HD = 23, SD = 32, VD = 86, H_DIM = 8, S_DIM = 8, V_DIM = 3;
}


//获取像素的量化值
int getDegree(uchar Hv,uchar  Sv,uchar  Vv) {
	auto a = int(Hv/(uchar)HD);
	auto b = (Sv >> 5);
	auto c = ((a << 3) + b);
	return c;
}
//获取图像的特征
std::vector getFeature(Mat& hsv) {
	auto hig = hsv.rows;
	auto wid = hsv.cols;
	auto feature = std::vector(H_DIM*S_DIM, 0);
	for (int i = 0; i < hig; i++) {
		for(int j=0;j(i, j);
			feature[getDegree(pixel[0], pixel[1], pixel[2])] += 1;
		}
	}
	return feature;
}


//线程入口:计算从start到end的 特征并写入文件
void getFeature_t(int start, int end, std::string outFile ) {
	if (start > end)
		return;
	std::vector prefixList(end+1-start,"");
	for (int i = start; i < end+1; i++) {
		prefixList[i-start] = std::to_string(i);
	}
	int maxRecord = 10;
	std::ofstream outFileStream(OUTPUT_FOLDER + outFile, std::fstream::out|std::fstream::app);
	if (!outFileStream.is_open())
		return;
	int count = 0;
    std::string	recordTowrite("");
	for (auto &prefix : prefixList) {
		cout << prefix<<"\t";
		std::string record("");
		std::string jpgfile = SAMPLE_FOLDER + prefix + ".jpg";
		Mat img = imread(jpgfile);
		Mat HSV;
		cvtColor(img, HSV, COLOR_BGR2HSV);
		auto feature = getFeature(HSV);
		record += prefix + " ";
		for (auto &one : feature) {
			record += std::to_string(one) + " ";
		}
		record += "\n";
		recordTowrite += record;
		count += 1;
		if (count >= maxRecord) {
			outFileStream< k;
	k.startTick();
	int ProcNum = 8;
	//41247
	int totalFileNum = 100;
	int lastJpg = 6500;
	std::vector ProcList ;
	int step = floor(totalFileNum / ProcNum);
	int remainCount = totalFileNum - step * ProcNum;
	std::vector distributeList(remainCount, 1);
	distributeList.insert(distributeList.end(), ProcNum-remainCount, 0);
	int endJpg = lastJpg + totalFileNum;
	for (int count = 0; count < ProcNum; count++) {
		int start = lastJpg + 1;
		int end = step + start - 1;
		if (end > endJpg)
			end = endJpg;
		end += distributeList[count];
		end = int(end);
		lastJpg = end;
		std::thread featureT(getFeature_t, start, end, std::to_string(start) + "_" + std::to_string(end) + ".txt");
		cout << start << " " << end << endl;;
		ProcList.push_back(std::move(featureT));
	}
	for (auto &thr : ProcList)
		thr.join();
	auto dura=k.tickAndGet();
	cout << dura << "s" << endl;
	return 0;
}

以下是python 提取HSV直方图特征的代码:

__date__ = '2018/12/20 16:56'
import cv2
import threading
import multiprocessing
import numpy as np
from math import  floor
import time

SAMPLE_FOLDER="frameSet/"
OUTPUT_FOLDER="output/"
#忽略了V这一层的影响
HD=23
SD=32
VD=86
H_DIM=8
S_DIM=8
V_DIM=3

#为了移位运算
#HD=32
#SD=64
#VD=64
#H_DIM=6
#S_DIM=4
#V_DIM=4
#获取分割后的值

def getDegree(Hv, Sv, Vv):
    a=(Hv//HD)
    b=(Sv>>5)
    c=((a<<3)+b)
    #if not (c>=0 and c<64):
        #print("k")

    return c

    #c=round(Vv/VD)
    #return 1
    #a=((Hv>>5)<<4)+((Sv>>6)<<2)+(Vv>>6)
    #if not (a>=0 and a< 96):
        #print("hh")
    #return a
    #a=(Hv>>5)
    #assert(a>=0 and a>6)
    #assert(b>=0 and b>6)
    #assert( c>=0 and c=0 and d< 96)
    ##a=int((Hv>>1)+(Sv>>4)+round(Vv>>6))
    #return int(d)


#获取图像的特征
def getFeature(hsv):
    hig,wid,dim=hsv.shape
    feature=[0 for e in range(0, H_DIM*S_DIM)]
    for row in  hsv:
        for pixel in row:
            feature[getDegree(pixel[0], pixel[1], pixel[2])]+=1
    return feature


#线程入口:计算从start到end的 特征并写入文件
def getFeature_t(start, end, outFile):
    if start>end:
        return
    prefixList=[str(e) for e in range(start, end+1)]
    maxRecord=10
    with open(OUTPUT_FOLDER+outFile, "a") as f:
        count=0
        recordTowrite=str()
        for prefix in prefixList:
            print(prefix)
            record=str()
            jpgfile=SAMPLE_FOLDER+prefix+".jpg"
            img=cv2.imread(jpgfile)
            HSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
            feature=getFeature(HSV)
            record+=prefix+" "
            for one in feature:
                record+=str(one)+" "
            record+="\n"
            recordTowrite+=record
            count+=1
            if count>=maxRecord:
                f.write(recordTowrite)
                recordTowrite=""
                count=0
         f.write(recordTowrite)
         f.close()


if __name__=="__main__":
    ProcNum=4
    #41247
    totalFileNum=100
    lastJpg=6500
    startCount=time.clock()
    ProcList=[]
    step=floor(totalFileNum/ProcNum)
    remainCount=totalFileNum-step*ProcNum
    distributeList=[1 for tmp in range(0, remainCount)]
    distributeList+=[0 for tmp in range(0, ProcNum-remainCount)]
    endJpg=lastJpg+totalFileNum

    for count in range(0,ProcNum):
        start=lastJpg+1
        end=step+start-1
        if end>endJpg:
            end=endJpg
        end+=distributeList[count]
        end=int(end)
        lastJpg=end
        first=multiprocessing.Process(target=getFeature_t, args=(start,end, str(start)+"_"+str(end)+".txt"))
        print(start, end)
        first.start()
        ProcList.append(first)
    for thr in ProcList:
        thr.join()
    endCount=time.clock()
    print(endCount-startCount)

c++代码在VS的release模式下,跑100图片仅需要 0.591537s,而python跑100张需要277s,足可以见效率之差

summary:前前后后花费 8个小时,重写了一遍,见了c++的快,python的慢。大作业总算有救了。。。

具体内容可见github: 镜头检测

你可能感兴趣的:(图像)