summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package.json14
-rw-r--r--scan.js202
-rw-r--r--scan.py65
3 files changed, 65 insertions, 216 deletions
diff --git a/package.json b/package.json
deleted file mode 100644
index b791717..0000000
--- a/package.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "name": "alpacaid",
- "version": "1.0.0",
- "description": "QR like code using an alpaca!",
- "main": "index.js",
- "scripts": {
- "test": "true"
- },
- "author": "Marvin Borner",
- "license": "BSD",
- "dependencies": {
- "opencv4nodejs": "^5.2.0"
- }
-}
diff --git a/scan.js b/scan.js
deleted file mode 100644
index b01a65a..0000000
--- a/scan.js
+++ /dev/null
@@ -1,202 +0,0 @@
-const cv = require("opencv4nodejs");
-
-class FinderPattern {
- constructor(a, b, c) {
- this.topLeft = new cv.Point(a);
- this.topRight = new cv.Point(b);
- this.bottomLeft = new cv.Point(c);
- }
-}
-
-function compareContourAreas(contour1, contour2) {
- return contour1.area > contour2.area;
-}
-
-function getContourCenter(vec) {
- let x = 0.0;
- let y = 0.0;
- for (let i = 0; i < vec.size(); i++) {
- x += vec[i].x;
- y += vec[i].y;
- }
- return new cv.Point(x / vec.size(), y / vec.size())
-}
-
-function isContourInsideContour(cont_in, cont_out) {
- for (let i = 0; i < cont_in.size(); i++) {
- if (cont_out.pointPolygonTest(cont_in[i]) <= 0) return false;
- }
- return true;
-}
-
-function findLimitedContours(contour, minPix, maxPix) {
- const contours = contour.findContours(cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE);
- console.log(contours.size());
- let m = 0;
- while (m < contours.size()) {
- if (contours[m].area <= minPix) {
- contours.erase(contours.begin())
- } else if (contours[m].area > maxPix) {
- contours.erase(contours.begin())
- } else ++m;
- }
- console.log(contours.size());
- return contours;
-}
-
-function getContourPair(contours) {
- let vectorPair = [];
- let flags = Array(contours.size()).fill(false);
- for (let i = 0; i < contours.size() - 1; i++) {
- if (flags[i]) continue;
- let temp = new cv.Contour();
- temp.push_back(contours[i]);
- for (let j = i + 1; j < contours.size(); j++) {
- if (isContourInsideContour(contours[j], contours[i])) {
- temp.push_back(contours[j]);
- flags[j] = true;
- }
- }
- if (temp.size() > 1) {
- vectorPair.push(temp)
- }
- }
- flags.clear();
- for (let i = 0; i < vectorPair.length; i++) {
- vectorPair[i] = vectorPair[i].sort((a, b) => compareContourAreas(a, b))
- }
- return vectorPair;
-}
-
-function eliminatePairs(vectorPair, minRatio, maxRatio) {
- console.log(maxRatio);
- let flag = false;
- let m = 0;
- while (m < vectorPair.size()) {
- flag = false;
- if (vectorPair[m].size() < 3) {
- vectorPair.erase(vectorPair.begin() + m);
- continue;
- }
- for (let i = 0; i < vectorPair[m].size() - 1; i++) {
- const area1 = vectorPair[m][i].area;
- const area2 = vectorPair[m][i + 1].area;
- if (area1 / area2 < minRatio || area1 / area2 > maxRatio) {
- vectorPair.erase(vectorPair.begin() + m);
- flag = true;
- break;
- }
- }
- if (!flag) {
- ++m;
- }
- }
- if (vectorPair.size() > 3) {
- eliminatePairs(vectorPair, minRatio, maxRatio * 0.9)
- }
-}
-
-function getDistance(a, b) {
- return Math.sqrt(((a.x - b.x) ** 2) + (a.y - b.y) ** 2);
-}
-
-function getFinderPattern(vectorPair) {
- const point1 = getContourCenter(vectorPair[0][vectorPair[0].size() - 1]);
- const point2 = getContourCenter(vectorPair[1][vectorPair[1].size() - 1]);
- const point3 = getContourCenter(vectorPair[2][vectorPair[2].size() - 1]);
- const distance1 = getDistance(point1, point2);
- const distance2 = getDistance(point1, point3);
- const distance3 = getDistance(point2, point3);
- let x1, y1, x2, y2, x3, y3, p1, p2, p3;
- const Max = Math.max.apply(Math, [distance1, distance2, distance3]);
- if (Max === distance1) {
- p1 = point1;
- p2 = point2;
- p3 = point3;
- } else if (Max === distance2) {
- p1 = point1;
- p2 = point3;
- p3 = point2;
- } else {
- p1 = point2;
- p2 = point3;
- p3 = point1;
- }
- x1 = p1.x;
- y1 = p1.y;
- x2 = p2.x;
- y2 = p2.y;
- x3 = p3.x;
- y3 = p3.y;
- if(x1 === x2){
- if(y1 > y2){
- if(x3 < x1){
- return FinderPattern(p3, p2, p1);
- }else{
- return FinderPattern(p3, p1, p2);
- }
- }else{
- if(x3 < x1){
- return FinderPattern(p3, p1, p2);
- }else{
- return FinderPattern(p3, p2, p1);
- }
- }
- }else{
- let newY = (y2 - y1) / (x2 - x1) * x3 + y1 - (y2 - y1) / (x2 - x1) * x1;
- if(x1 > x2){
- if(newY < y3){
- return FinderPattern(p3, p2, p1);
- }else{
- return FinderPattern(p3, p1, p2);
- }
- }else{
- if(newY < y3){
- return FinderPattern(p3, p1, p2);
- }else{
- return FinderPattern(p3, p2, p1);
- }
- }
- }
-}
-
-const ori = cv.imread("./example.jpg");
-const gray = ori.cvtColor(cv.COLOR_GRAY2BGR);
-let canny = new cv.Mat;
-gray.copyTo(canny);
-const bin = gray.threshold(0, 255, cv.THRESH_OTSU);
-let contour = new cv.Mat;
-bin.copyTo(contour);
-let contours = findLimitedContours(contour, 8.00, 0.2 * ori.cols * ori.rows);
-
-
-if(!contours.empty()) contours = contours.sort((a, b) => compareContourAreas(a, b));
-const vectorPair = getContourPair(contours);
-eliminatePairs(vectorPair, 1.0, 10.0);
-fPattern = getFinderPattern(vectorPair);
-let drawing = new cv.Mat;
-ori.copyTo(drawing);
-
-drawing.drawCircle(fPattern.topLeft, 3, new cv.Vec3(255, 0, 0), 2, 8, 0);
-drawing.drawCircle(fPattern.topRight, 3, new cv.Vec3(0,255,0), 2, 8, 0);
-drawing.drawCircle(fPattern.bottomLeft, 3, new cv.Vec3(0,0,255), 2, 8, 0);
-
-let vectorSource = [new cv.Point2(0, 0)];
-let vectorDestination = [new cv.Point2(0, 0)];
-vectorSource.push(fPattern.topLeft);
-vectorSource.push(fPattern.topRight);
-vectorSource.push(fPattern.bottomLeft);
-vectorDestination.push(new cv.Point2(20, 20));
-vectorDestination.push(new cv.Point2(120, 20));
-vectorDestination.push(new cv.Point2(20, 120));
-const affineTrans = cv.getAffineTransform(vectorSource, vectorDestination);
-const warped = ori.warpAffine(affineTrans, ori.size());
-const qrColor = warped(new cv.Rect(0, 0, 140, 140));
-const qrColorGray = qrColor.cvtColor(cv.COLOR_GRAY2RGB);
-const qrBin = qrColorGray.threshold(0, 255, cv.THRESH_OTSU);
-
-cv.imshow("binary", bin);
-cv.imshow("canny", canny);
-cv.imshow("finder patterns", drawing);
-cv.imshow("binaried qr code", qrBin);
-cv.waitKey();
diff --git a/scan.py b/scan.py
new file mode 100644
index 0000000..75e14bb
--- /dev/null
+++ b/scan.py
@@ -0,0 +1,65 @@
+import cv2
+import imutils
+import numpy as np
+
+
+def order_points(pts):
+ rect = np.zeros((4, 2), dtype="float32")
+ s = pts.sum(axis=1)
+ rect[0] = pts[np.argmin(s)]
+ rect[2] = pts[np.argmax(s)]
+ diff = np.diff(pts, axis=1)
+ rect[1] = pts[np.argmin(diff)]
+ rect[3] = pts[np.argmax(diff)]
+ return rect
+
+
+def four_point_transform(image, pts):
+ rect = order_points(pts)
+ (tl, tr, br, bl) = rect
+ widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
+ widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
+ maxWidth = max(int(widthA), int(widthB))
+
+ heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
+ heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
+ maxHeight = max(int(heightA), int(heightB))
+
+ dst = np.array([
+ [0, 0],
+ [maxWidth - 1, 0],
+ [maxWidth - 1, maxHeight - 1],
+ [0, maxHeight - 1]], dtype="float32")
+
+ M = cv2.getPerspectiveTransform(rect, dst)
+ warped = cv2.warpPerspective(image, M, (maxWidth, maxHeight))
+
+ return warped
+
+
+image = cv2.imread("example.jpg")
+ratio = image.shape[0] / 500.0
+orig = image.copy()
+
+gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
+gray = cv2.GaussianBlur(gray, (5, 5), 0)
+edged = cv2.Canny(gray, 75, 200)
+
+cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
+cnts = imutils.grab_contours(cnts)
+cnts = sorted(cnts, key=cv2.contourArea, reverse=True)[:5]
+
+for c in cnts:
+ peri = cv2.arcLength(c, True)
+ approx = cv2.approxPolyDP(c, 0.02 * peri, True)
+ if len(approx) == 4:
+ screenCnt = approx
+ break
+
+cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 2)
+
+warped = four_point_transform(orig, screenCnt.reshape(4, 2) * ratio)
+
+cv2.imshow("Original", imutils.resize(orig, height=650))
+cv2.imshow("Scanned", imutils.resize(warped, height=650))
+cv2.waitKey(0)