Báo cáo tập nhóm lần 5_Nhóm Danh sách thành viên: Lê Minh Nhựt _ Mssv: 1512374 Diệp Vĩ Cường _ Mssv: 1510347 Nguyễn Anh Tuấn _ Mssv: 1513834 Võ Thanh Phong _ Mssv: 1512464 I) Chương trinh C++ #include #include #include #include #include #include "stdint.h" #include #include "math.h" #include using namespace std; using namespace cv; const string trackbarWindowName = "Trackbars"; int H_MIN = 10; // minimum Hue int H_MAX = 180; // maximum Hue int S_MIN = 0; // minimum Saturation int S_MAX = 255; // maximum Saturation int V_MIN = 0; // minimum Value int V_MAX = 255; //maximum Value void on_trackbar(int, void*) { // Doing nothing here since we are going to handle the changes in some other place } void createTrackbars() { namedWindow(trackbarWindowName, 1); createTrackbar("H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar); createTrackbar("H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar); createTrackbar("S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar); createTrackbar("S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar); createTrackbar("V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar); createTrackbar("V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar); } float innerAngle(float px1, float py1, float px2, float py2, float cx1, float cy1) { float dist1 = std::sqrt((px1 - cx1)*(px1 - cx1) + (py1 - cy1)*(py1 - cy1)); float dist2 = std::sqrt((px2 - cx1)*(px2 - cx1) + (py2 - cy1)*(py2 - cy1)); float Ax, Ay; float Bx, By; float Cx, Cy; //find closest point to C //printf("dist = %lf %lf\n", dist1, dist2); Cx = cx1; Cy = cy1; if (dist1 < dist2) { Bx = px1; By = py1; Ax = px2; Ay = py2; } else { Bx = px2; By = py2; Ax = px1; Ay = py1; } float Q1 = Cx - Ax; float Q2 = Cy - Ay; float P1 = Bx - Ax; float P2 = By - Ay; float A = std::acos((P1*Q1 + P2*Q2) / (std::sqrt(P1*P1 + P2*P2) * std::sqrt(Q1*Q1 + Q2*Q2))); A = A * 180 / CV_PI; return A; } int main() { int H_MIN_1, H_MAX_1, S_MIN_1, S_MAX_1, V_MIN_1, V_MAX_1; Mat Dialate(Size(640, 420), CV_8UC1); Mat Dialate_1(Size(640, 420), CV_8UC1); Mat Erode(Size(640, 420), CV_8UC1); Mat Erode_1(Size(640, 420), CV_8UC1); Mat bw(Size(640, 420), CV_8UC1); Mat bw_1(Size(640, 420), CV_8UC1); const char* windowName = "Fingertip detection"; createTrackbars(); ///////////////////////////////////////////////////////////// //GET CONTOURS.SIZE() cv::Mat pic = cv::imread("D:/data-apps/VS2015/bantay4.png"); cv::Mat img2 = cv::imread("D:/data-apps/VS2015/bantay4.png"); //cv::Mat pic = sample; Size kSize; kSize.height = 3; kSize.width = 3; double sigma = 0.3*(3 / - 1) + 0.8; GaussianBlur(pic, pic, kSize, sigma, 0.0, 4); Mat hsv(Size(640, 420), CV_8UC3); cvtColor(pic, hsv, CV_RGB2HSV); //inRange(hsv, Scalar(106, 61, 77), Scalar(117, 218, 196), bw_1);//hinh1(1 hand) inRange(hsv, Scalar(104, 23, 10), Scalar(131, 255, 255), bw_1);//hinh2(4 hands) //inRange(hsv, Scalar(86, 26, 0), Scalar(126, 255, 255), bw_1);//fist cv::erode(bw_1, Erode_1, cv::Mat(), cv::Point(-1, -1)); cv::dilate(Erode_1, Dialate_1, cv::Mat(), cv::Point(-1, -1), 2); // Contour detection std::vector contours; std::vector hierarchy; cv::findContours(Dialate_1, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0)); int contourssize = contours.size(); //////////////////////////////////////////////////// //read image std::vector croppedImg(contourssize);//croppedImg[i] with i = const value cv::Mat img; int chieurong = img2.size().width; //lay chieu rong cua image int chieucao = img2.size().height; //lay chieu cao cua image int dorong = chieurong / contours.size(); for (int i = 0; i < contourssize; i++) { img2(cv::Rect(dorong*i, 0, dorong, chieucao)).copyTo(croppedImg[i]); } for (int tam = 0; tam < contourssize; tam++) { img = croppedImg[tam]; //separate image based on contourssize stringstream stream; Size kSize; kSize.height = 3; kSize.width = 3; double sigma = 0.3*(3 / - 1) + 0.8; GaussianBlur(img, img, kSize, sigma, 0.0, 4); Mat hsv(Size(640, 420), CV_8UC3); cvtColor(img, hsv, CV_RGB2HSV); //inRange(hsv, Scalar(106, 61, 77), Scalar(117, 218, 196), bw_1);//hinh1(1 hand) inRange(hsv, Scalar(104, 23, 10), Scalar(131, 255, 255), bw_1);//hinh2(4 hands) //inRange(hsv, Scalar(86, 26, 0), Scalar(126, 255, 255), bw_1);//fist cv::erode(bw_1, Erode_1, cv::Mat(), cv::Point(-1, -1)); cv::dilate(Erode_1, Dialate_1, cv::Mat(), cv::Point(-1, -1), 2); // Contour detection std::vector contours; std::vector hierarchy; cv::findContours(Dialate_1, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0)); printf("contour size: %d\n", contours.size()); size_t largestContour = 0; for (size_t i = 1; i < contours.size(); i++) { if (cv::contourArea(contours[i]) >= cv::contourArea(contours[largestContour])) largestContour = i; } cv::drawContours(img, contours, largestContour, cv::Scalar(0, 0, 255), 2); // Convex hull if (!contours.empty()) { std::vector hull(1); cv::convexHull(cv::Mat(contours[largestContour]), hull[0], false); cv::drawContours(img, hull, 0, cv::Scalar(0, 255, 0), 3); if (hull[0].size() > 2) { std::vector hullIndexes; cv::convexHull(cv::Mat(contours[largestContour]), hullIndexes, true); std::vector convexityDefects; cv::convexityDefects(cv::Mat(contours[largestContour]), hullIndexes, convexityDefects); cv::Rect boundingBox = cv::boundingRect(hull[0]); cv::rectangle(img, boundingBox, cv::Scalar(255, 0, 0)); cv::Point center = cv::Point(boundingBox.x + boundingBox.width / 2, boundingBox.y + boundingBox.height / 2); cv::Point conner_rect = cv::Point(boundingBox.x, boundingBox.y + boundingBox.height); std::vector validPoints_p1; std::vector validPoints_p2; std::vector validPoints_p3; for (size_t i = 0; i < convexityDefects.size(); i++) { cv::Point p1 = contours[largestContour][convexityDefects[i][0]]; cv::Point p2 = contours[largestContour][convexityDefects[i][1]]; cv::Point p3 = contours[largestContour][convexityDefects[i][2]]; double angle = std::atan2(center.y - p1.y, center.x - p1.x) * 180 / CV_PI; double inAngle = innerAngle(p1.x, p1.y, p2.x, p2.y, p3.x, p3.y); double length = std::sqrt(std::pow(p1.x - p3.x, 2) + std::pow(p1.y - p3.y, 2)); if (/*angle > -30 && angle < 160 &&*/ std::abs(inAngle) > 20 && std::abs(inAngle) < 120 /*&& length > 0.1 * boundingBox.height */) { validPoints_p1.push_back(p1); validPoints_p3.push_back(p3); validPoints_p2.push_back(p2); } } if (validPoints_p1.size() > 1) //khi validPoints_p1.size() == { double length_1 = std::sqrt(std::pow(validPoints_p1[1].x - validPoints_p2[1].x, 2) + std::pow(validPoints_p1[1].y - validPoints_p2[1].y, 2)); if (length_1 < boundingBox.width / 2) { for (size_t i = 0; i < validPoints_p3.size(); i++) { cv::circle(img, validPoints_p3[i], 9, cv::Scalar(0, 255, 0), 2); } stream boundingBox.width / 2)) { for (size_t i = 0; i < validPoints_p1.size(); i++) { cv::circle(img, validPoints_p1[i], 9, cv::Scalar(0, 255, 0), 2); } stream 100 and h>100: cv2.rectangle(crop_image,(x,y),(x+w,y+h),(0,0,255),0) # Find convex hull hull = cv2.convexHull(contour) # Draw contour drawing = np.zeros(crop_image.shape,np.uint8) cv2.drawContours(drawing,[contour],-1,(0,255,0),0) cv2.drawContours(drawing,[hull],-1,(0,0,255),0) # Find convexity defects hull = cv2.convexHull(contour, returnPoints=False) defects = cv2.convexityDefects(contour,hull) # Use cosine rule to find angle of the far point from the start and end point i.e the convex points (the finger # tips) for all defects count_defects = for i in range(defects.shape[0]): s,e,f,d = defects[i,0] start = tuple(contour[s][0]) end = tuple(contour[e][0]) far = tuple(contour[f][0]) a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2) # end[0]=end[x], end[1]=end[y] b = math.sqrt((far[0] - start[0])**2 + (far[1] - start[1])**2) c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2) angle = (math.acos((b**2 + c**2 - a**2)/(2*b*c))*180)/3.14 # if angle