之前一直是用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,足可以见效率之差