我使用OpenCV在Python和C ++中实现了HOG面部检测器。我试图将两个实现中的代码保持完全相同。但是,我在两者中得到了不同的结果。在Python中,它可以正常工作,但是,在C ++中它显示完全不正确的结果。下面是他们的输出示例(第一个在Python中,第二个在C ++中):
首先,我为两个实现培训了一个OpenCV线性SVM分类器,并将它们保存在XML文件(模型文件)中。然后,我从模型(XML文件)中提取系数(用于在测试过程中自定义HOG检测器),使用this code进行Python实现,this code进行C ++实现。也就是说,这些系数将成为测试过程中函数 setSVMDetector(const std :: vector< float> input_coefficients)的输入。
理想情况下,这些系数应该相同,因为它们是从同一数据集计算并使用OpenCV。我已经通过将这些系数值保存在两个实现的文本文件中来手动检查这些系数值,并发现它们几乎相同。所以,我希望我未来的定制HOG探测器在两种实现中的工作方式几乎相同。
以下是使用两种实现方式检测测试图像中的面部的测试代码。
Python实现:
import cv2
im = cv2.imread("..\\test_imgs\\1.png", 0) # test image
hog = cv2.HOGDescriptor((96, 128), (16,16), (8,8), (8,8), 9)
coeffs = pickle.load(open("coeffs_from_model")) # load coeffs already computed from model
hog.setSVMDetector( np.array(coeffs)) # customize HOG detector
found, w = hog.detectMultiScale(im, winStride=(8,8), padding=(32,32), scale=4.05)
draw_detections(im, found_filtered) # method for drawing BBs on image
C ++实现:
cv::Mat im = cv::imread("..\\test_imgs\\1.png", 0);
cv::HOGDescriptor hog(cv::Size(96, 128), cv::Size(16, 16), cv::Size(8, 8), cv::Size(8, 8), 9);
LinearSVM svm; // check the link
svm.load(model.c_str());
std::vector<float> coeffs;
svm.getSupportVector(coeffs); // compute coeffs from model
hog.setSVMDetector(coeffs); // customize HOG detector
std::vector<cv::Rect> found; // holds the detected BBs
hog.detectMultiScale(im, found, 0, cv::Size(8, 8), cv::Size(32, 32), 4.05);
drawLocations(im, found, cv::Scalar(0, 255, 0)); // method for drawing BBs on the image.
为了检查为C ++计算的系数是否不正确。我在Python实现中使用它们,有趣的是,它们的工作方式完全相同。所以,现在我不知道为什么尽管有正确的系数,C ++实现中的HOG对象仍然无法正常工作。
我在C ++中使用了与HOG相同的HOG对象初始化,并且在两个实现中保持代码几乎相同,因为它们都使用相同的OpenCV。
答案 0 :(得分:1)
我现在得到了答案。上面写的两个代码都是正确的。问题出在用于培训的标签上。我正在使用&#34; 0&#34; (面子类)和&#34; 1&#34; (非face class)作为两个实现中的标签。
对于Python实现,这个labellings正常工作,但是,对于C ++实现,它似乎必须是&#34; + 1&#34; (面子类)和&#34; -1&#34; (非面部类)我发现它here。在该示例中,在源代码的末尾,标签提供为:
// Set up training data
float labels[4] = {1.0, -1.0, -1.0, -1.0};
Mat labelsMat(4, 1, CV_32FC1, labels);