我想建立一个可以玩井字游戏的人工智能。首先,我正在尝试使用OpenCV来“看到”电路板。为了构建我的分类器,我使用了以下命令:
opencv_createsamples -vec pos_out.vec -img board.png -w 48 -h 48 -bg neg.txt -num 50
opencv_traincascade -data training_data/ -vec pos_out.vec -numPos 50 -numNeg 7 -bg neg.txt -w 48 -h 48
我没有很多照片,所以七张背景(负片)照片只是桌面背景。积极的图片是一个井字游戏的截图,裁剪,所以只是董事会可见。
使用分类器的代码只是将分类器作为参数,以及它应该为游戏板寻找的图片:
#include <opencv2/opencv.hpp>
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
CascadeClassifier board_cascade;
int main(int argc, char **argv)
{
CvCapture* capture;
Mat frame;
if (!board_cascade.load(argv[1])) {
fprintf(stderr, "Error loading cascade file %s.", argv[1]);
return -1;
}
frame = imread(argv[2], 1);
for (int i=0; i<10; i++)
detectAndDisplay(frame);
waitKey(0);
return 0;
}
void detectAndDisplay(Mat frame)
{
int i;
vector<Rect> boards;
Mat frame_gray;
cvtColor(frame, frame_gray, CV_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
board_cascade.detectMultiScale(frame_gray, boards, 1.5, 8, 0, Size(500, 500));
for(i=0; i<boards.size(); i++) {
Point center(boards[i].x + boards[i].width/2, boards[i].y+boards[i].height/2);
ellipse(frame, center, Size(boards[i].width/2, boards[i].height/2), 0, 0, 360, Scalar(255, 0, 0), 2, 8, 0);
printf("Width: %d height: %d x: %d y: %d\n", boards[i].width, boards[i].height, boards[i].x, boards[i].y);;
}
if (i > 0) {
int startx = boards[0].x;
int starty = boards[0].y;
int width = boards[0].width;
int height = boards[0].height;
for (i=1; i<=6; i+=2) {
for (int j=1; j<=6; j+=2) {
Point center(startx + (width/6 * i), starty + (height/6 * j));
ellipse(frame, center, Size(30, 30), 0, 0, 360, Scalar(255, 0, 0), 2, 8, 0);
}
}
}
imshow("Board detection", frame);
}
This是board.png,我将其用作“积极”形象。 This是图像中的纸板与“正”图像的尺寸相同时的结果,而this是不是时的结果。正如你所看到的,当电路板大小相同时,它确实合理,但是当电路板尺寸较大时,它会合理地好。
我以前从来没有“训练”过分类器,所以我希望得到一些关于如何改进结果的指示。添加更多阳性样本会有帮助吗?或者是否有一些我应该在某处修改的参数?
谢谢!