|
#include <opencv2/objdetect/objdetect.hpp> |
|
#include <opencv2/imgproc/imgproc.hpp> |
|
#include <opencv2/highgui/highgui.hpp> |
|
|
|
using namespace cv; |
|
using namespace std; |
|
|
|
#define SCALE 1.75 |
|
|
|
bool isInside(Point pt1, Point pt2, int x, int y) |
|
{ |
|
if (pt1.x < x && pt1.y < y && x < pt2.x && y < pt2.y) |
|
return true; |
|
return false; |
|
} |
|
|
|
int main(int argc, char *argv[]) |
|
{ |
|
// arguments |
|
if (argc < 2) { |
|
fprintf(stderr, "%s: missing operand: cannot detect video file.\n", argv[0]); |
|
return -1; |
|
} |
|
|
|
// cascade |
|
string cascadeName = "./lbpcascade_animeface.xml"; |
|
CascadeClassifier cascade; |
|
if(!cascade.load(cascadeName)) { |
|
fprintf(stderr, "%s: cannot open file: ./lbpcascade_animeface.xml\n", argv[0]); |
|
return -1; |
|
} |
|
|
|
// capture |
|
VideoCapture capture; |
|
if (!capture.open(argv[1])) { |
|
fprintf(stderr, "%s: invalid source: cannot open video.\n", argv[0]); |
|
return -1; |
|
} |
|
|
|
// print info |
|
//printf("frame: %f\n", capture.get(CV_CAP_PROP_FRAME_COUNT)); |
|
|
|
// prepare window |
|
namedWindow("frame", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO); |
|
namedWindow("image", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO); |
|
|
|
// variables |
|
Mat frame, smooth, colors, filter; |
|
vector<Rect> faces; |
|
Point center, pt1, pt2; |
|
int i = 0, max = capture.get(CV_CAP_PROP_FRAME_COUNT), radius; |
|
|
|
// start capture |
|
capture >> frame; |
|
Mat small(saturate_cast<int>(frame.rows/SCALE), saturate_cast<int>(frame.cols/SCALE), CV_8UC1); |
|
|
|
while (i < max) { |
|
// scale down image |
|
resize(frame, small, small.size(), 0, 0, INTER_LINEAR); |
|
// image, rect, scale, minimum rect number, flag, minimum rect size |
|
cascade.detectMultiScale(small, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30)); |
|
// draw |
|
vector<Rect>::const_iterator r = faces.begin(); |
|
bool found = false; |
|
Size size = frame.size(); |
|
int width = size.width, height = size.height; |
|
filter = Mat(Size(width, height), CV_8UC3); |
|
filter = Scalar(0,0,0); |
|
for (; r != faces.end(); ++r) { |
|
// face position coordinates |
|
center.x = saturate_cast<int>((r->x + r->width * 0.5) * SCALE); |
|
center.y = saturate_cast<int>((r->y + r->height * 0.5) * SCALE); |
|
radius = saturate_cast<int>((r->width + r->height) * 0.25 * SCALE); |
|
pt1.x = center.x - radius; |
|
pt1.y = center.y - radius; |
|
pt2.x = center.x + radius; |
|
pt2.y = center.y + radius; |
|
// HSV detection |
|
medianBlur(frame, smooth, 3); // blur |
|
cvtColor(smooth, colors, CV_BGR2HSV, 3); // color conversion |
|
MatIterator_<Vec3b> it = colors.begin<Vec3b>(), it_end = colors.end<Vec3b>(); |
|
for (; it != it_end; ++it) { |
|
Vec3b& filter = *it; |
|
filter[0] = 40; |
|
} |
|
//for (int y = 0; y < height; y++) { |
|
// for (int x = 0; x < width; x++) { |
|
// // being inside the face |
|
// if (isInside(pt1, pt2, x, y)) { |
|
// // stepping color to HSV |
|
// int c = colors.step * y + (x * 3); |
|
// int H = colors.data[c]; |
|
// int S = colors.data[c+1]; |
|
// int V = colors.data[c+2]; |
|
// printf("%d\n", H); |
|
// if (60 <= H && H <= 80) { // is face |
|
// filter.data[c] = 255; |
|
// } |
|
// } |
|
// } |
|
//} |
|
// finally draw rectangle |
|
rectangle(frame, pt1, pt2, Scalar(80, 80, 255), 3, 8, 0); |
|
} |
|
// wait some key to quit |
|
if(waitKey(30) >= 0) break; |
|
// show window |
|
imshow("frame", frame); |
|
imshow("image", filter); |
|
// skip frames for speed |
|
capture.set(CV_CAP_PROP_POS_FRAMES, (i = i + 4)); |
|
capture >> frame; |
|
} |
|
return 0; |
|
} |
|
|