Last active
August 29, 2015 14:10
-
-
Save nuttt/c91f77cdecce53557d26 to your computer and use it in GitHub Desktop.
Hand
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // main.cpp | |
| // Hand | |
| // | |
| // Created by Nuttapon Pattanavijit on 11/24/14. | |
| // Copyright (c) 2014 nut. All rights reserved. | |
| // | |
| #include <opencv2/core/core.hpp> | |
| #include <opencv2/highgui/highgui.hpp> | |
| #include <opencv2/imgproc/imgproc.hpp> | |
| #include <opencv2/ml/ml.hpp> | |
| #include <iostream> | |
| #include <deque> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string> | |
| #include <vector> | |
| #include <math.h> | |
| #include <algorithm> | |
| #include <string> | |
| #define pii pair<int,int> | |
| #define vii vector<pair<int,int> > | |
| #define vint vector<int> | |
| #define dii deque<pair<int,int> > | |
| #define INPUT_SIZE 20 | |
| #define OUTPUT_SIZE 4 | |
| using namespace cv; | |
| using namespace std; | |
| void rotate2D(const cv::Mat & src, cv::Mat & dst, const double degrees); | |
| // Nasty global variable | |
| Mat img, imgb, imgc, imgd, img_out,imgat, img_out2, img_out3, imgat2; | |
| int dilation_size; | |
| int morph_elem = 0; | |
| int morph_size = 0; | |
| int morph_operator = 0; | |
| int const max_operator = 4; | |
| int const max_elem = 2; | |
| int const max_kernel_size = 21; | |
| int blur_size = 1, blur_max = 10; | |
| int gsize = 12, gd = 0; | |
| int bri = 150, con = 0; | |
| //int bri = 170, con = 100; | |
| int equ = 0; | |
| int thresholdVal = 0; | |
| int edgeThresh = 1; | |
| int lowThreshold = 10; | |
| int const max_lowThreshold = 100; | |
| int canny_ratio = 3; | |
| int kernel_size = 3; | |
| int minPts = 5; | |
| // int epsDist = 2; | |
| int epsDist = 17; | |
| int minCluster = 3; | |
| int blockSize = 10; | |
| //int meanSubtract = 2; | |
| int meanSubtract = 0; | |
| vector<Mat> top5mat_output; | |
| vector<int> top5mat_label; | |
| vector<Mat> matNN; | |
| vector<int> labelNN; | |
| //End of nasty global variable | |
| CvANN_MLP loadNN() { | |
| CvANN_MLP nnetwork; | |
| CvFileStorage* storage = cvOpenFileStorage( "/Users/nuttt/Dropbox/computer_vision/nn.xml", 0, CV_STORAGE_READ ); | |
| CvFileNode *n = cvGetFileNodeByName(storage,0,"nnetwork"); | |
| nnetwork.read(storage,n); | |
| cvReleaseFileStorage(&storage); | |
| return nnetwork; | |
| } | |
| int dist(int x1, int x2, int y1, int y2) { | |
| return (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2); | |
| } | |
| vii neighborQuery(Mat &m, int mi, int mj) { | |
| int i,j; | |
| int row = m.rows; | |
| int col = m.cols; | |
| vii neighbor; | |
| for(i=mi-epsDist; i<=mi+epsDist;i++) { | |
| for(j=mj-epsDist;j<=mj+epsDist;j++) { | |
| if(i >= 0 && i < row && j >= 0 && j < col) { | |
| if(m.at<unsigned char>(i,j)) { | |
| if(dist(i,mi,j,mj) <= epsDist*2) { | |
| neighbor.push_back(pii(i,j)); | |
| } | |
| } | |
| } | |
| } | |
| } | |
| return neighbor; | |
| } | |
| bool mycompare(pii a, pii b) { | |
| return a.second > b.second; | |
| } | |
| Mat DBScan(Mat input) { | |
| top5mat_output.clear(); | |
| top5mat_label.clear(); | |
| Mat output_rgb[3]; | |
| output_rgb[0] = Mat::zeros(input.size(), CV_8UC1); | |
| output_rgb[1] = Mat::zeros(input.size(), CV_8UC1); | |
| output_rgb[2] = Mat::zeros(input.size(), CV_8UC1); | |
| Mat output; | |
| Mat cluster = Mat::zeros(input.size(), CV_32SC1); | |
| Mat visit = Mat::zeros(input.size(), CV_8UC1); | |
| Mat noise = Mat::zeros(input.size(), CV_8UC1); | |
| int row = input.rows; | |
| int col = input.cols; | |
| int i,j,k,l; | |
| int clusterNo = 0; | |
| dii queue; | |
| vii count; | |
| count.push_back(pii(0,0)); | |
| for(i=0;i<row;i++) { | |
| for(j=0;j<col;j++) { | |
| queue.clear(); | |
| if(!visit.at<unsigned char>(i,j) && input.at<unsigned char>(i,j)) { | |
| visit.at<unsigned char>(i,j) = 255; | |
| vii neighbor = neighborQuery(input, i, j); | |
| if(neighbor.size() < minPts) { | |
| noise.at<unsigned char>(i,j) = 255; | |
| //cout << "noise" << rand() << endl; | |
| } else { | |
| clusterNo++; | |
| count.push_back(pii(clusterNo,0)); | |
| int thisCluster = clusterNo; | |
| for(k=0;k<neighbor.size();k++) { | |
| queue.push_back(neighbor[k]); | |
| } | |
| cluster.at<int>(i,j) = thisCluster; | |
| // Expand cluster | |
| while(!queue.empty()) { | |
| pii p = queue.front(); | |
| queue.pop_front(); | |
| if(!visit.at<unsigned char>(p.first, p.second)) { | |
| visit.at<unsigned char>(p.first, p.second) = 255; | |
| neighbor = neighborQuery(input, p.first, p.second); | |
| if(neighbor.size() >= minPts) { | |
| for(k=0;k<neighbor.size();k++) { | |
| queue.push_back(neighbor[k]); | |
| } | |
| } | |
| } | |
| if(cluster.at<int>(p.first, p.second) == 0) { | |
| cluster.at<int>(p.first, p.second) = thisCluster; | |
| count[thisCluster].second++; | |
| } | |
| } | |
| } | |
| } | |
| } | |
| } | |
| sort(count.begin(), count.end(), mycompare); | |
| vint top5; | |
| for(i=0;i<5;i++) { | |
| top5.push_back(count[i].first); | |
| } | |
| int c; | |
| // clusterX.clear(); | |
| // clusterY.clear(); | |
| for(int i=0;i<5;i++) { | |
| vector<double> vecx; | |
| vector<double> vecy; | |
| // clusterX.push_back(vecx); | |
| // clusterY.push_back(vecy); | |
| } | |
| Mat top5mat[5]; | |
| for(i=0;i<5;i++) { | |
| top5mat[i] = Mat::zeros(input.rows, input.cols, CV_8UC1); | |
| } | |
| //cout << "--------- Start Data ----------" << endl; | |
| for(i=0;i<row;i++) { | |
| for(j=0;j<col;j++) { | |
| c = cluster.at<int>(i,j); | |
| if(c && find(top5.begin(), top5.end(), c) != top5.end()) { | |
| srand(c); | |
| output_rgb[0].at<unsigned char>(i,j) = rand() % 156 + 100; | |
| output_rgb[1].at<unsigned char>(i,j) = rand() % 156 + 100; | |
| output_rgb[2].at<unsigned char>(i,j) = rand() % 156 + 100; | |
| int pos = (int)(find(top5.begin(), top5.end(), c) - top5.begin() + 1); | |
| // cout << pos << " " << i << " " << j << endl; | |
| // clusterX[pos-1].push_back(i); | |
| // clusterY[pos-1].push_back(j); | |
| top5mat[pos-1].at<unsigned char>(i,j) = 255; | |
| } else if(c) { | |
| srand(c); | |
| /* | |
| output_rgb[0].at<unsigned char>(i,j) = rand() % 50; | |
| output_rgb[1].at<unsigned char>(i,j) = rand() % 50; | |
| output_rgb[2].at<unsigned char>(i,j) = rand() % 50; | |
| */ | |
| output_rgb[0].at<unsigned char>(i,j) = 0; | |
| output_rgb[1].at<unsigned char>(i,j) = 0; | |
| output_rgb[2].at<unsigned char>(i,j) = 0; | |
| } | |
| } | |
| } | |
| //cout << "--------- End Data ----------" << endl; | |
| merge(output_rgb, 3, output); | |
| // imshow("cluster", output); | |
| for(i=0;i<5;i++) { | |
| top5mat_output.push_back(top5mat[i]); | |
| // imwrite(outpath+filename+"_"+to_string(i)+filetypeout, top5mat[i]); | |
| } | |
| return output; | |
| } | |
| int main(int argc, const char * argv[]) { | |
| // insert code here... | |
| namedWindow("test"); | |
| // string inputPath = argv[1]; | |
| // string outputPath = argv[2]; | |
| string inputPath = "/Users/nuttt/in.jpg"; | |
| string outputPath = "/Users/nuttt/out.jpg"; | |
| int ibegin = 434; | |
| int iend = 834; | |
| int jbegin = 185; | |
| int jend = 585; | |
| Mat img_input = imread(inputPath); | |
| rotate2D(img_input, img_input, 270.0); | |
| Mat img = Mat::zeros(400, 400, CV_8UC3); | |
| for(int i=ibegin;i<iend;i++) { | |
| for(int j=jbegin;j<jend;j++) { | |
| // cout << i-ibegin << " " << j-jbegi << endl; | |
| Vec3b a = img_input.at<Vec3b>(i,j); | |
| img.at<Vec3b>(i-ibegin, j-jbegin) = a; | |
| } | |
| } | |
| //imshow("test", img_input); | |
| //waitKey(1000); | |
| //imshow("test", img); | |
| //waitKey(1000); | |
| resize(img, img, Size(400,400)); | |
| imwrite("/Users/nuttt/fuckhand.jpg", img); | |
| cvtColor( img, img, CV_BGR2GRAY ); | |
| GaussianBlur(img, imgc, Size(gsize*2+1, gsize*2+1), gd); | |
| //imshow("test", imgc); | |
| //waitKey(1000); | |
| imgc.convertTo(imgd, -1, 1 + con / 100.0, bri / 10.0 - 15); | |
| //imshow("test", imgd); | |
| //waitKey(1000); | |
| adaptiveThreshold(imgd, imgat, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, blockSize*2+1, meanSubtract); | |
| //imshow("test", 255-imgat); | |
| //waitKey(1000); | |
| imgat2 = DBScan(255-imgat); | |
| //imshow("test", imgat2); | |
| //waitKey(5000); | |
| // Neural Network | |
| Mat test1, test2, test1out; | |
| CvANN_MLP nnetwork = loadNN(); | |
| for(int i = 0; i < top5mat_output.size(); i++) { | |
| top5mat_output[i].copyTo(test1); | |
| top5mat_output[i].copyTo(test2); | |
| // imshow("test", test2); | |
| // waitKey(1000); | |
| test1.convertTo(test1, CV_32F); | |
| resize(test1, test1, Size(INPUT_SIZE,INPUT_SIZE)); | |
| test1 = test1.reshape(0, 1); | |
| nnetwork.predict(test1, test1out); | |
| float max = -9999999.0; | |
| int max_id = -1; | |
| for(int j=0; j<test1out.cols; j++) { | |
| float val = test1out.at<float>(0,j); | |
| // cout << j << ":" << val << endl; | |
| if(val > max) { | |
| max = val; | |
| max_id = j; | |
| } | |
| } | |
| // cout << max_id << endl; | |
| Mat test3[5]; | |
| test2.copyTo(test3[i]); | |
| if(max > 0.5) { | |
| // imshow("test", test3[i]); | |
| // waitKey(1000); | |
| matNN.push_back(test3[i]); | |
| labelNN.push_back(max_id); | |
| } | |
| } | |
| Mat img_fin; | |
| img_input.copyTo(img_fin); | |
| for(int k = 0; k < matNN.size(); k++) { | |
| Mat line; | |
| matNN[k].copyTo(line); | |
| // cout << line.rows << " " << line.cols << endl; | |
| for(int i = 0; i < line.rows; i++) { | |
| for(int j = 0; j < line.cols; j++) { | |
| if(line.at<unsigned char>(i,j)) { | |
| img_fin.at<Vec3b>(i+ibegin,j+jbegin) = Vec3b(255,255,255); | |
| } | |
| } | |
| } | |
| } | |
| imwrite(outputPath, img_fin); | |
| return 0; | |
| } | |
| void rotate2D(const cv::Mat & src, cv::Mat & dst, const double degrees) | |
| { | |
| cv::Mat frame, frameRotated; | |
| int diagonal = (int)sqrt(src.cols * src.cols + src.rows * src.rows); | |
| int newWidth = diagonal; | |
| int newHeight = diagonal; | |
| int offsetX = (newWidth - src.cols) / 2; | |
| int offsetY = (newHeight - src.rows) / 2; | |
| cv::Mat targetMat(newWidth, newHeight, src.type(), cv::Scalar(0)); | |
| cv::Point2f src_center(targetMat.cols / 2.0f, targetMat.rows / 2.0f); | |
| src.copyTo(frame); | |
| frame.copyTo(targetMat.rowRange(offsetY, offsetY + | |
| frame.rows).colRange(offsetX, offsetX + frame.cols)); | |
| cv::Mat rot_mat = cv::getRotationMatrix2D(src_center, degrees, 1.0); | |
| cv::warpAffine(targetMat, frameRotated, rot_mat, targetMat.size()); | |
| cv::Rect bound_Rect(frame.cols, frame.rows, 0, 0); | |
| int x1 = offsetX; | |
| int x2 = offsetX + frame.cols; | |
| int x3 = offsetX; | |
| int x4 = offsetX + frame.cols; | |
| int y1 = offsetY; | |
| int y2 = offsetY; | |
| int y3 = offsetY + frame.rows; | |
| int y4 = offsetY + frame.rows; | |
| cv::Mat co_Ordinate = (cv::Mat_<double>(3, 4) << x1, x2, x3, x4, | |
| y1, y2, y3, y4, | |
| 1, 1, 1, 1 ); | |
| cv::Mat RotCo_Ordinate = rot_mat * co_Ordinate; | |
| for (int i = 0; i < 4; ++i) { | |
| if (RotCo_Ordinate.at<double>(0, i) < bound_Rect.x) | |
| bound_Rect.x = (int)RotCo_Ordinate.at<double>(0, i); | |
| if (RotCo_Ordinate.at<double>(1, i) < bound_Rect.y) | |
| bound_Rect.y = RotCo_Ordinate.at<double>(1, i); | |
| } | |
| for (int i = 0; i < 4; ++i) { | |
| if (RotCo_Ordinate.at<double>(0, i) > bound_Rect.width) | |
| bound_Rect.width = (int)RotCo_Ordinate.at<double>(0, i); | |
| if (RotCo_Ordinate.at<double>(1, i) > bound_Rect.height) | |
| bound_Rect.height = RotCo_Ordinate.at<double>(1, i); | |
| } | |
| bound_Rect.width = bound_Rect.width - bound_Rect.x; | |
| bound_Rect.height = bound_Rect.height - bound_Rect.y; | |
| if (bound_Rect.x < 0) | |
| bound_Rect.x = 0; | |
| if (bound_Rect.y < 0) | |
| bound_Rect.y = 0; | |
| if (bound_Rect.width > frameRotated.cols) | |
| bound_Rect.width = frameRotated.cols; | |
| if (bound_Rect.height > frameRotated.rows) | |
| bound_Rect.height = frameRotated.rows; | |
| cv::Mat ROI = frameRotated(bound_Rect); | |
| ROI.copyTo(dst); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment