{"action":"created","comment":{"url":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/comments/107834104","pull_request_review_id":28828763,"id":107834104,"diff_hunk":"@@ -0,0 +1,154 @@\n+import java.util.ArrayList;\n+import java.util.List;\n+\n+import org.opencv.core.Core;\n+import org.opencv.core.Mat;\n+import org.opencv.core.MatOfKeyPoint;\n+import org.opencv.core.MatOfPoint;\n+import org.opencv.core.Point;\n+import org.opencv.core.Rect;\n+import org.opencv.core.Scalar;\n+import org.opencv.core.Size;\n+//import org.opencv.features2d.FeatureDetector;\n+//import org.opencv.features2d.Features2d;\n+import org.opencv.imgcodecs.Imgcodecs;\n+import org.opencv.imgproc.Imgproc;\n+\n+public class NumberPlayScanner{\n+  Mat image;\n+  Mat grayscaleImage;\n+  Mat binImage;\n+  Mat boundaryDeletedImage;\n+  \n+  List<MatOfPoint> contours;\n+  Mat hierarchy;\n+  List<Point> sudokuPoints;\n+  \n+  MatOfKeyPoint detectedPoints;\n+  \n+  public NumberPlayScanner(Mat image){\n+    this.image = image;\n+    this.grayscaleImage = new Mat();\n+    this.binImage = new Mat();\n+    this.boundaryDeletedImage = new Mat();\n+    \n+    this.contours = new ArrayList<MatOfPoint>();\n+    this.hierarchy = new Mat();\n+    \n+    this.detectedPoints = new MatOfKeyPoint();\n+  }\n+  \n+  public void run(){\n+    imageBinarization();\n+    \n+    contourDetection();\n+    \n+    boundaryDeletion();\n+    \n+    divideCells();\n+  }\n+  \n+  private void imageBinarization(){\n+    Imgproc.cvtColor(this.image, grayscaleImage, Imgproc.COLOR_RGB2GRAY);\n+    \n+    //obtain an image easier to do image processing by gaussian blur\n+    Imgproc.GaussianBlur(this.grayscaleImage, this.grayscaleImage, new Size(5, 5), 1, 1);\n+    \n+    //Adaptive thresholding is used. Need to find most appropriate number for the last two ints of inputs\n+    Imgproc.adaptiveThreshold(this.grayscaleImage, this.binImage, 255,\n+                              Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, 7, 10);\n+    Core.bitwise_not(this.binImage, this.binImage);\n+    Imgproc.dilate(this.binImage, this.binImage, new Mat());\n+    \n+    //debug process for binary image\n+    writeImage(this.grayscaleImage, \"output/grayscale.png\");\n+    writeImage(this.binImage, \"output/binary.png\");\n+  }\n+  \n+  private void contourDetection(){\n+    Mat contourDetectedImage = this.image.clone();\n+    //copy and paste code, working fine currently. Should look into it to find better suited logic\n+    Imgproc.findContours(this.binImage, this.contours, this.hierarchy,\n+                         Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1);\n+    \n+    //debug process for contour detection\n+    Imgproc.drawContours(contourDetectedImage, this.contours, -1, new Scalar(0, 0, 255), 3);\n+    writeImage(contourDetectedImage, \"output/detectedContours.png\");\n+    \n+    System.out.println(String.format(\"%d\\n\", this.contours.size()));\n+    for(int i = 0; i < this.contours.size(); i++){\n+      System.out.println(\"\" + this.contours.get(i).dump());\n+    }\n+    \n+    //currently assuming that there is only one contour in the scene.\n+    this.sudokuPoints = this.contours.get(0).toList();\n+    for(int i = 0; i < this.sudokuPoints.size(); i ++){\n+      System.out.println(String.format((\"x:%f, y:%f\"), this.sudokuPoints.get(i).x, this.sudokuPoints.get(i).y));\n+    }\n+  }\n+  \n+  //adjust the sudoku board straight so that it can be easily handled later\n+  private void boardAdjustment(){\n+    \n+  }\n+  \n+  //Delete boundaries in order not to hinder number recognition later\n+  private void boundaryDeletion(){\n+    Mat mask = new Mat();\n+    this.boundaryDeletedImage = this.binImage.clone();\n+    \n+    Imgproc.floodFill(this.boundaryDeletedImage, mask, this.sudokuPoints.get(0), new Scalar(0,0,0));\n+    \n+    writeImage(this.boundaryDeletedImage, \"output/boundaryDeletedImage.png\");\n+  }\n+  \n+  //divide the detected board into 9x9 sudoku problem to detect numbers in it\n+  private void divideCells(){\n+    Core.bitwise_not(this.boundaryDeletedImage, this.boundaryDeletedImage);\n+    double x1 = Math.pow(10, 10), x2 = 0, y1 = Math.pow(10, 10), y2 = 0;\n+    \n+    for(int i = 0; i < this.sudokuPoints.size(); i++){\n+      x1 = Math.min(x1, this.sudokuPoints.get(i).x);\n+      x2 = Math.max(x2, this.sudokuPoints.get(i).x);\n+      y1 = Math.min(y1, this.sudokuPoints.get(i).y);\n+      y2 = Math.max(y2, this.sudokuPoints.get(i).y);\n+    }\n+    double width = (x2 - x1) / 9, height = (y2 - y1) / 9;\n+    \n+    Point upperLeft = new Point(x1, y1);\n+    double h = 0;\n+    for(int i = 0; i < 9; i++){\n+      h += height;\n+      for(int j = 0; j < 9; j++){\n+        Point cell = new Point(upperLeft.x + width, upperLeft.y + height);\n+        Rect r = new Rect(upperLeft, cell);\n+        \n+        String filename = \"output/trim/cell\" + (j+1) + \"x\" + (i+1) + \".png\";\n+        //image trimming by Rectangle r\n+        Mat dividedImage = new Mat(this.boundaryDeletedImage, r);\n+        Imgcodecs.imwrite(filename, dividedImage);\n+        upperLeft.x = cell.x;\n+      }\n+      upperLeft.x = x1;\n+      upperLeft.y = y1 + h;\n+    }\n+  }\n+  \n+  private void writeImage(Mat outputImage, String path){\n+    //debug process\n+    System.out.println(String.format(\"Write %s\\n\", path));","path":"NumberPlayScanner/src/NumberPlayScanner.java","position":139,"original_position":139,"commit_id":"484b9a1da0bafcf85e6de023e25ba5ce46124a1f","original_commit_id":"484b9a1da0bafcf85e6de023e25ba5ce46124a1f","user":{"login":"koba-e964","id":3303362,"avatar_url":"https://avatars1.githubusercontent.com/u/3303362?v=3","gravatar_id":"","url":"https://api.github.com/users/koba-e964","html_url":"https://github.com/koba-e964","followers_url":"https://api.github.com/users/koba-e964/followers","following_url":"https://api.github.com/users/koba-e964/following{/other_user}","gists_url":"https://api.github.com/users/koba-e964/gists{/gist_id}","starred_url":"https://api.github.com/users/koba-e964/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/koba-e964/subscriptions","organizations_url":"https://api.github.com/users/koba-e964/orgs","repos_url":"https://api.github.com/users/koba-e964/repos","events_url":"https://api.github.com/users/koba-e964/events{/privacy}","received_events_url":"https://api.github.com/users/koba-e964/received_events","type":"User","site_admin":false},"body":"Same here.","created_at":"2017-03-24T04:41:24Z","updated_at":"2017-03-24T04:48:46Z","html_url":"https://github.com/koba-e964/sparkle-number-place/pull/1#discussion_r107834104","pull_request_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/comments/107834104"},"html":{"href":"https://github.com/koba-e964/sparkle-number-place/pull/1#discussion_r107834104"},"pull_request":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/1","id":112383910,"html_url":"https://github.com/koba-e964/sparkle-number-place/pull/1","diff_url":"https://github.com/koba-e964/sparkle-number-place/pull/1.diff","patch_url":"https://github.com/koba-e964/sparkle-number-place/pull/1.patch","issue_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/issues/1","number":1,"state":"open","locked":false,"title":"first commit of NumberPlay board scanner","user":{"login":"IrnBrew","id":17334421,"avatar_url":"https://avatars3.githubusercontent.com/u/17334421?v=3","gravatar_id":"","url":"https://api.github.com/users/IrnBrew","html_url":"https://github.com/IrnBrew","followers_url":"https://api.github.com/users/IrnBrew/followers","following_url":"https://api.github.com/users/IrnBrew/following{/other_user}","gists_url":"https://api.github.com/users/IrnBrew/gists{/gist_id}","starred_url":"https://api.github.com/users/IrnBrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IrnBrew/subscriptions","organizations_url":"https://api.github.com/users/IrnBrew/orgs","repos_url":"https://api.github.com/users/IrnBrew/repos","events_url":"https://api.github.com/users/IrnBrew/events{/privacy}","received_events_url":"https://api.github.com/users/IrnBrew/received_events","type":"User","site_admin":false},"body":"it's WIP to be honest. It works fine, but puts unrealistic assumptions to input data.\r\nIf you have any comment on things like the style of code, plz let me know.","created_at":"2017-03-24T03:58:31Z","updated_at":"2017-03-24T04:48:46Z","closed_at":null,"merged_at":null,"merge_commit_sha":"944606fd983560237e5a326af25fe7df8282860a","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/1/commits","review_comments_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/1/comments","review_comment_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/comments{/number}","comments_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/issues/1/comments","statuses_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/statuses/484b9a1da0bafcf85e6de023e25ba5ce46124a1f","head":{"label":"IrnBrew:master","ref":"master","sha":"484b9a1da0bafcf85e6de023e25ba5ce46124a1f","user":{"login":"IrnBrew","id":17334421,"avatar_url":"https://avatars3.githubusercontent.com/u/17334421?v=3","gravatar_id":"","url":"https://api.github.com/users/IrnBrew","html_url":"https://github.com/IrnBrew","followers_url":"https://api.github.com/users/IrnBrew/followers","following_url":"https://api.github.com/users/IrnBrew/following{/other_user}","gists_url":"https://api.github.com/users/IrnBrew/gists{/gist_id}","starred_url":"https://api.github.com/users/IrnBrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IrnBrew/subscriptions","organizations_url":"https://api.github.com/users/IrnBrew/orgs","repos_url":"https://api.github.com/users/IrnBrew/repos","events_url":"https://api.github.com/users/IrnBrew/events{/privacy}","received_events_url":"https://api.github.com/users/IrnBrew/received_events","type":"User","site_admin":false},"repo":{"id":84432899,"name":"sparkle-number-place","full_name":"IrnBrew/sparkle-number-place","owner":{"login":"IrnBrew","id":17334421,"avatar_url":"https://avatars3.githubusercontent.com/u/17334421?v=3","gravatar_id":"","url":"https://api.github.com/users/IrnBrew","html_url":"https://github.com/IrnBrew","followers_url":"https://api.github.com/users/IrnBrew/followers","following_url":"https://api.github.com/users/IrnBrew/following{/other_user}","gists_url":"https://api.github.com/users/IrnBrew/gists{/gist_id}","starred_url":"https://api.github.com/users/IrnBrew/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IrnBrew/subscriptions","organizations_url":"https://api.github.com/users/IrnBrew/orgs","repos_url":"https://api.github.com/users/IrnBrew/repos","events_url":"https://api.github.com/users/IrnBrew/events{/privacy}","received_events_url":"https://api.github.com/users/IrnBrew/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/IrnBrew/sparkle-number-place","description":null,"fork":true,"url":"https://api.github.com/repos/IrnBrew/sparkle-number-place","forks_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/forks","keys_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/keys{/key_id}","collaborators_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/teams","hooks_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/hooks","issue_events_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/issues/events{/number}","events_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/events","assignees_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/assignees{/user}","branches_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/branches{/branch}","tags_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/tags","blobs_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/git/refs{/sha}","trees_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/git/trees{/sha}","statuses_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/statuses/{sha}","languages_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/languages","stargazers_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/stargazers","contributors_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/contributors","subscribers_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/subscribers","subscription_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/subscription","commits_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/commits{/sha}","git_commits_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/git/commits{/sha}","comments_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/comments{/number}","issue_comment_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/issues/comments{/number}","contents_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/contents/{+path}","compare_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/compare/{base}...{head}","merges_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/merges","archive_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/downloads","issues_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/issues{/number}","pulls_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/pulls{/number}","milestones_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/milestones{/number}","notifications_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/labels{/name}","releases_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/releases{/id}","deployments_url":"https://api.github.com/repos/IrnBrew/sparkle-number-place/deployments","created_at":"2017-03-09T11:09:23Z","updated_at":"2017-03-24T03:49:21Z","pushed_at":"2017-03-24T04:28:19Z","git_url":"git://github.com/IrnBrew/sparkle-number-place.git","ssh_url":"git@github.com:IrnBrew/sparkle-number-place.git","clone_url":"https://github.com/IrnBrew/sparkle-number-place.git","svn_url":"https://github.com/IrnBrew/sparkle-number-place","homepage":null,"size":14,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"koba-e964:master","ref":"master","sha":"a30029f7cfc4897b9fbcc2eaa26f52356512ca5e","user":{"login":"koba-e964","id":3303362,"avatar_url":"https://avatars1.githubusercontent.com/u/3303362?v=3","gravatar_id":"","url":"https://api.github.com/users/koba-e964","html_url":"https://github.com/koba-e964","followers_url":"https://api.github.com/users/koba-e964/followers","following_url":"https://api.github.com/users/koba-e964/following{/other_user}","gists_url":"https://api.github.com/users/koba-e964/gists{/gist_id}","starred_url":"https://api.github.com/users/koba-e964/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/koba-e964/subscriptions","organizations_url":"https://api.github.com/users/koba-e964/orgs","repos_url":"https://api.github.com/users/koba-e964/repos","events_url":"https://api.github.com/users/koba-e964/events{/privacy}","received_events_url":"https://api.github.com/users/koba-e964/received_events","type":"User","site_admin":false},"repo":{"id":84429331,"name":"sparkle-number-place","full_name":"koba-e964/sparkle-number-place","owner":{"login":"koba-e964","id":3303362,"avatar_url":"https://avatars1.githubusercontent.com/u/3303362?v=3","gravatar_id":"","url":"https://api.github.com/users/koba-e964","html_url":"https://github.com/koba-e964","followers_url":"https://api.github.com/users/koba-e964/followers","following_url":"https://api.github.com/users/koba-e964/following{/other_user}","gists_url":"https://api.github.com/users/koba-e964/gists{/gist_id}","starred_url":"https://api.github.com/users/koba-e964/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/koba-e964/subscriptions","organizations_url":"https://api.github.com/users/koba-e964/orgs","repos_url":"https://api.github.com/users/koba-e964/repos","events_url":"https://api.github.com/users/koba-e964/events{/privacy}","received_events_url":"https://api.github.com/users/koba-e964/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/koba-e964/sparkle-number-place","description":null,"fork":false,"url":"https://api.github.com/repos/koba-e964/sparkle-number-place","forks_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/forks","keys_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/keys{/key_id}","collaborators_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/teams","hooks_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/hooks","issue_events_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/issues/events{/number}","events_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/events","assignees_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/assignees{/user}","branches_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/branches{/branch}","tags_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/tags","blobs_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/git/refs{/sha}","trees_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/git/trees{/sha}","statuses_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/statuses/{sha}","languages_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/languages","stargazers_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/stargazers","contributors_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/contributors","subscribers_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/subscribers","subscription_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/subscription","commits_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/commits{/sha}","git_commits_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/git/commits{/sha}","comments_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/comments{/number}","issue_comment_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/issues/comments{/number}","contents_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/contents/{+path}","compare_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/compare/{base}...{head}","merges_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/merges","archive_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/downloads","issues_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/issues{/number}","pulls_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls{/number}","milestones_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/milestones{/number}","notifications_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/labels{/name}","releases_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/releases{/id}","deployments_url":"https://api.github.com/repos/koba-e964/sparkle-number-place/deployments","created_at":"2017-03-09T10:28:23Z","updated_at":"2017-03-09T12:12:17Z","pushed_at":"2017-03-24T04:28:20Z","git_url":"git://github.com/koba-e964/sparkle-number-place.git","ssh_url":"git@github.com:koba-e964/sparkle-number-place.git","clone_url":"https://github.com/koba-e964/sparkle-number-place.git","svn_url":"https://github.com/koba-e964/sparkle-number-place","homepage":null,"size":12,"stargazers_count":0,"watchers_count":0,"language":"Ruby","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/1"},"html":{"href":"https://github.com/koba-e964/sparkle-number-place/pull/1"},"issue":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/issues/1"},"comments":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/koba-e964/sparkle-number-place/statuses/484b9a1da0bafcf85e6de023e25ba5ce46124a1f"}}}}
{"actor":{"display_login":"koba-e964"}}