Moving around the testing notebooks. Autocropping is about done with exception to any new versions or converting the stuff to C code. Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
431 lines
13 KiB
Plaintext
431 lines
13 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 14,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# https://docs.opencv.org/3.4/d9/db0/tutorial_hough_lines.html\n",
|
|
"# https://medium.com/@9sphere/machine-vision-recipes-deskewing-document-images-e17827894c34\n",
|
|
"# https://towardsdatascience.com/pre-processing-in-ocr-fc231c6035a7"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"#initially for deskewing and cropping. moving to a doc for just cropping now that deskewing"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 15,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import cv2\n",
|
|
"import numpy as np\n",
|
|
"import math\n",
|
|
"import myfunctions as mf\n",
|
|
"\n",
|
|
"import scipy.stats as st"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 16,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# def ResizeWithAspectRatio(image, width=None, height=None, inter=cv2.INTER_AREA, retscale=False):\n",
|
|
"# dim = None\n",
|
|
"# (h, w) = image.shape[:2]\n",
|
|
"\n",
|
|
"# if width is None and height is None:\n",
|
|
"# if (retscale == True):\n",
|
|
"# return (image, 1)\n",
|
|
"# return image\n",
|
|
"# if width is None:\n",
|
|
"# r = height / float(h)\n",
|
|
"# dim = (int(w * r), height)\n",
|
|
"# else:\n",
|
|
"# r = width / float(w)\n",
|
|
"# dim = (width, int(h * r))\n",
|
|
"\n",
|
|
"# if (retscale == True):\n",
|
|
"# # print(\"hi\")\n",
|
|
"# return (cv2.resize(image, dim, interpolation=inter), 1/r)\n",
|
|
"# return cv2.resize(image, dim, interpolation=inter)\n",
|
|
"\n",
|
|
"\n",
|
|
"# class SquarePad:\n",
|
|
"# def __init__(self, fill):\n",
|
|
"# self.fill = fill\n",
|
|
" \n",
|
|
"# def __call__(self, image):\n",
|
|
"# w, h = image.shape[1], image.shape[0]\n",
|
|
"# max_wh = np.max([w, h])\n",
|
|
"# hp = int((max_wh - w) / 2)\n",
|
|
"# vp = int((max_wh - h) / 2)\n",
|
|
"# padding = (hp, vp, hp, vp)\n",
|
|
"# return cv2.copyMakeBorder(image, vp, vp, hp, hp, cv2.BORDER_CONSTANT, self.fill)\n",
|
|
" \n",
|
|
" \n",
|
|
" \n",
|
|
"# def rotate(img, angle):\n",
|
|
"# rows,cols = img.shape[0], img.shape[1]\n",
|
|
"# M = cv2.getRotationMatrix2D((cols/2,rows/2),angle,1)\n",
|
|
"# dst = cv2.warpAffine(img,M,(cols,rows))\n",
|
|
"# return dst"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 17,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# def morphologyCrop(image):\n",
|
|
"# # convert to grayscale\n",
|
|
"# gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)\n",
|
|
"\n",
|
|
"# # threshold\n",
|
|
"# thresh = cv2.threshold(gray, 170, 255, cv2.THRESH_BINARY)[1]\n",
|
|
"\n",
|
|
"# # apply morphology\n",
|
|
"# kernel = np.ones((7,7), np.uint8)\n",
|
|
"# morph = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)\n",
|
|
"# kernel = np.ones((9,9), np.uint8)\n",
|
|
"# morph = cv2.morphologyEx(morph, cv2.MORPH_ERODE, kernel)\n",
|
|
"\n",
|
|
"# # get largest contour\n",
|
|
"# contours = cv2.findContours(morph, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)\n",
|
|
"# contours = contours[0] if len(contours) == 2 else contours[1]\n",
|
|
"# area_thresh = 0\n",
|
|
"# for c in contours:\n",
|
|
"# area = cv2.contourArea(c)\n",
|
|
"# if area > area_thresh:\n",
|
|
"# area_thresh = area\n",
|
|
"# big_contour = c\n",
|
|
"\n",
|
|
"\n",
|
|
"# # get bounding box\n",
|
|
"# x,y,w,h = cv2.boundingRect(big_contour)\n",
|
|
"\n",
|
|
"# # draw filled contour on black background\n",
|
|
"# mask = np.zeros_like(gray)\n",
|
|
"# mask = cv2.merge([mask,mask,mask])\n",
|
|
"# cv2.drawContours(mask, [big_contour], -1, (255,255,255), cv2.FILLED)\n",
|
|
"\n",
|
|
"# # apply mask to input\n",
|
|
"# result1 = image.copy()\n",
|
|
"# result1 = cv2.bitwise_and(result1, mask)\n",
|
|
"\n",
|
|
"# # crop result\n",
|
|
"# result2 = result1[y:y+h, x:x+w]\n",
|
|
"# return result2"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 18,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"# x = -2*np.pi/3\n",
|
|
"# print(x)\n",
|
|
"# print(np.pi/3)\n",
|
|
"# print(x % np.pi)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 19,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# def lineAngle(line):\n",
|
|
"# # print(line)\n",
|
|
"# angle = (math.atan2(line[3] - line[1], line[2] - line[0]) % np.pi) - (np.pi/2)\n",
|
|
"# return angle\n",
|
|
" \n",
|
|
"# def WithinXDegrees(lines, margin):\n",
|
|
"# # outlines = np.array([[]])\n",
|
|
"# outlines = np.empty((0, 4))\n",
|
|
"# # print(outlines.shape)\n",
|
|
"# for line in lines:\n",
|
|
"# # print(type(line))\n",
|
|
"# # print(abs(lineAngle(line[0])))\n",
|
|
"# if (np.rad2deg(abs(lineAngle(line[0]))) <= margin):\n",
|
|
"# outlines = np.append(outlines, [line[0]], axis=0)\n",
|
|
"# return outlines\n",
|
|
"\n",
|
|
"# def lineBoundingRect(lines):\n",
|
|
"# maxvals = lines.max(0)\n",
|
|
"# minvals = lines.min(0)\n",
|
|
"# boundingrect = (min(minvals[0],minvals[2]), min(minvals[1],minvals[3]), max(maxvals[0],maxvals[2]),max(maxvals[1],maxvals[3]))\n",
|
|
"# return boundingrect\n",
|
|
"# # print(lines.max(0))\n",
|
|
"# # print(type(lines))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 20,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"img = cv2.imread('./test_images/IMG_7605.jpg')\n",
|
|
"img = mf.SquarePad(fill=255)(img)\n",
|
|
"img = mf.rotate(img, 54)\n",
|
|
"img = mf.morphologyCrop(mf.ResizeWithAspectRatio(img,1000))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 21,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
|
|
"# img = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY)[1]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 22,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"cv2.imshow(\"Detected Lines (in red) - Standard Hough Line Transform\", mf.ResizeWithAspectRatio(mf.SquarePad(fill=255)(img), 1000))\n",
|
|
"cv2.waitKey(0)\n",
|
|
"cv2.destroyAllWindows()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 23,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"resizedimg = mf.ResizeWithAspectRatio(mf.SquarePad(fill=255)(img), 500)\n",
|
|
"\n",
|
|
"# cv2.imshow(\"Detected Lines (in red) - Standard Hough Line Transform\", img)\n",
|
|
"# cv2.waitKey(0)\n",
|
|
"# cv2.destroyAllWindows()\n",
|
|
"\n",
|
|
"gray = cv2.cvtColor(resizedimg ,cv2.COLOR_BGR2GRAY)\n",
|
|
"gray = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY)[1]\n",
|
|
"cdst = resizedimg.copy()\n",
|
|
"\n",
|
|
"\n",
|
|
"dst = cv2.Canny(gray, 50, 200, None, 3)\n",
|
|
"lines = cv2.HoughLines(dst, 1, np.pi/180, 150, None, 0, 0)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 24,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"angles = np.zeros(len(lines))\n",
|
|
"if lines is not None:\n",
|
|
" for i in range(0, len(lines)):\n",
|
|
" rho = lines[i][0][0]\n",
|
|
" theta = lines[i][0][1]\n",
|
|
" a = math.cos(theta)\n",
|
|
" b = math.sin(theta)\n",
|
|
" x0 = a * rho\n",
|
|
" y0 = b * rho\n",
|
|
" unroundedpt1 = (x0 + 1000*(-b), y0 + 1000*(a))\n",
|
|
" unroundedpt2 = (x0 - 1000*(-b), y0 - 1000*(a))\n",
|
|
" pt1 = (int(unroundedpt1[0]), int(unroundedpt1[1]))\n",
|
|
" pt2 = (int(unroundedpt2[0]), int(unroundedpt2[1]))\n",
|
|
" v1_theta = math.atan2(pt1[1], pt1[0])\n",
|
|
" v2_theta = math.atan2(pt2[1], pt2[0])\n",
|
|
" # print(math.atan2(unroundedpt2[1] - unroundedpt1[1], unroundedpt2[0] - unroundedpt1[0]) % np.pi)\n",
|
|
" # print(lineAngle((unroundedpt1[0], unroundedpt1[1], unroundedpt2[0], unroundedpt2[1])))\n",
|
|
" # angles[i] = math.atan2(unroundedpt2[1] - unroundedpt1[1], unroundedpt2[0] - unroundedpt1[0]) % np.pi\n",
|
|
" angles[i] = mf.lineAngle((unroundedpt1[0], unroundedpt1[1], unroundedpt2[0], unroundedpt2[1]))\n",
|
|
" cv2.line(cdst, pt1, pt2, (0,0,255), 3, cv2.LINE_AA)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 25,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"-56.7228217179515\n",
|
|
"-56.7228217179515\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# print(st.mode(np.around(angles, decimals=1)))\n",
|
|
"mode = st.mode(np.around(angles, decimals=2))[0]\n",
|
|
"print(np.rad2deg(mode))\n",
|
|
"# slope = math.tan(np.deg2rad(mode))\n",
|
|
"# print(slope)\n",
|
|
"# myy0 = 0\n",
|
|
"# p1 = [0,myy0]\n",
|
|
"# p2 = [0,myy0]\n",
|
|
"# while (math.dist(p1, p2) < 5000):\n",
|
|
"# p2[0] += 0.5\n",
|
|
"# p2[1] += 0.5*slope*1000\n",
|
|
"# p2[1] = int(p2[1])\n",
|
|
"# print(p2)\n",
|
|
"# cv2.line(cdst, p1, p2, (0,255,0), 3, cv2.LINE_AA)\n",
|
|
"# rotationangle = np.rad2deg(mode)-90\n",
|
|
"rotationangle = np.rad2deg(mode)\n",
|
|
"print(rotationangle)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 26,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"cv2.imshow(\"Detected Lines (in red) - Standard Hough Line Transform\", cdst)\n",
|
|
"cv2.waitKey(0)\n",
|
|
"cv2.destroyAllWindows()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 27,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# cv2.imshow(\"Detected Lines (in red) - Standard Hough Line Transform\", rotate(cdst,rotationangle))\n",
|
|
"# cv2.waitKey(0)\n",
|
|
"# cv2.destroyAllWindows()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 28,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"rotatedimg = mf.SquarePad(fill=255)(mf.rotate(img, rotationangle))\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 29,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# cv2.imshow(\"Rotated Image\", ResizeWithAspectRatio(rotatedimg, 1000))\n",
|
|
"# cv2.waitKey(0)\n",
|
|
"# cv2.destroyAllWindows()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 30,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"resizedrotatedimg = mf.ResizeWithAspectRatio(rotatedimg, 500)\n",
|
|
"gray1 = cv2.cvtColor(resizedrotatedimg, cv2.COLOR_BGR2GRAY)\n",
|
|
"dst1 = cv2.Canny(gray1, 0, 500, None, 3)\n",
|
|
"cdstP = resizedrotatedimg.copy()\n",
|
|
"cdstPmargin = cdstP.copy()\n",
|
|
"linesP = cv2.HoughLinesP(dst1, 1, np.pi / 180, 30, None, 100, 30)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 31,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"if linesP is not None:\n",
|
|
" for i in range(0, len(linesP)):\n",
|
|
" l = linesP[i][0]\n",
|
|
" cv2.line(cdstP, (l[0], l[1]), (l[2], l[3]), (0,0,255), 3, cv2.LINE_AA)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 32,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"cv2.imshow(\"Detected Lines (in red) - Standard Hough Line Transform\", cdstP)\n",
|
|
"cv2.waitKey(0)\n",
|
|
"cv2.destroyAllWindows()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 33,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# print(linesP)\n",
|
|
"marginlines = mf.WithinXDegrees(linesP, 2)\n",
|
|
"# print(marginlines)\n",
|
|
"if marginlines is not None:\n",
|
|
" for i in range(0, len(marginlines)):\n",
|
|
" l = marginlines[i]\n",
|
|
" cv2.line(cdstPmargin, (int(l[0]), int(l[1])), (int(l[2]), int(l[3])), (0,0,255), 3, cv2.LINE_AA)\n",
|
|
" \n",
|
|
"# boundingrectout = mf.lineBoundingRect(marginlines)\n",
|
|
"# # print(boundingrectout)\n",
|
|
"# cdstPmargin = cv2.rectangle(cdstPmargin,(int(boundingrectout[0]),int(boundingrectout[1])),(int(boundingrectout[2]),int(boundingrectout[3])),(0,255,0),2)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 34,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"cv2.imshow(\"Detected Lines (in red) - Standard Hough Line Transform\", cdstPmargin)\n",
|
|
"cv2.waitKey(0)\n",
|
|
"cv2.destroyAllWindows()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Python 3",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.10.12"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|