Temp final point in trying to get a black and white version

Have to move on to training and working on the app.
have it crop and rotate and will let yolov7 train on that
and I would imagine it will work fine. Don't have the time to try
figure out the whiteout still.

Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
This commit is contained in:
Ethan Wellenreiter 2023-12-05 14:47:02 -05:00
parent 6a27931e8b
commit 8cb39fbbf1
2 changed files with 322 additions and 449 deletions

View File

@ -2,9 +2,20 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1895,
"execution_count": 1,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/usr/local/lib/python3.10/dist-packages/torchvision/datapoints/__init__.py:12: UserWarning: The torchvision.datapoints and torchvision.transforms.v2 namespaces are still Beta. While we do not expect major breaking changes, some APIs may still change according to user feedback. Please submit any feedback you may have in this issue: https://github.com/pytorch/vision/issues/6753, and you can also check out https://github.com/pytorch/vision/issues/7319 to learn more about the APIs that we suspect might involve future changes. You can silence this warning by calling torchvision.disable_beta_transforms_warning().\n",
" warnings.warn(_BETA_TRANSFORMS_WARNING)\n",
"/usr/local/lib/python3.10/dist-packages/torchvision/transforms/v2/__init__.py:54: UserWarning: The torchvision.datapoints and torchvision.transforms.v2 namespaces are still Beta. While we do not expect major breaking changes, some APIs may still change according to user feedback. Please submit any feedback you may have in this issue: https://github.com/pytorch/vision/issues/6753, and you can also check out https://github.com/pytorch/vision/issues/7319 to learn more about the APIs that we suspect might involve future changes. You can silence this warning by calling torchvision.disable_beta_transforms_warning().\n",
" warnings.warn(_BETA_TRANSFORMS_WARNING)\n"
]
}
],
"source": [
"import cv2\n",
"import myfunctions as mf\n",
@ -15,7 +26,7 @@
},
{
"cell_type": "code",
"execution_count": 1896,
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
@ -55,7 +66,7 @@
},
{
"cell_type": "code",
"execution_count": 1897,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
@ -77,7 +88,7 @@
},
{
"cell_type": "code",
"execution_count": 1898,
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
@ -91,7 +102,7 @@
},
{
"cell_type": "code",
"execution_count": 1899,
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
@ -102,7 +113,7 @@
},
{
"cell_type": "code",
"execution_count": 1900,
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
@ -152,29 +163,92 @@
" paddedl = mf.padWithColour(threshl, sdim*2, sdim*2, fill=0)\n",
" # return paddedl\n",
" \n",
" morphedl = paddedl\n",
" morphedl = cv2.morphologyEx(morphedl, cv2.MORPH_OPEN, kernel, iterations=1)\n",
" \n",
" # morphedl = 255-cv2.morphologyEx(255-threshl, cv2.MORPH_OPEN, kernel, iterations=3)\n",
" morphedl = paddedl\n",
" # morphedl = cv2.morphologyEx(morphedl, cv2.MORPH_ERODE, kernel, iterations=1)\n",
" morphed1l = cv2.morphologyEx(morphedl, cv2.MORPH_ERODE, kernelell, iterations=1)\n",
"\n",
" # return morphedl\n",
" \n",
" canny = cv2.Canny(morphedl, 0, 500)\n",
" contours, heirarchy = cv2.findContours(morphed1l, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" biggestcontour = max(contours, key=cv2.contourArea)\n",
" \n",
" \n",
" blank = np.full(labl.shape, 255, dtype=np.uint8)\n",
" mask1 = blank.copy()\n",
" mask1 = mf.padWithColour(mask1, sdim*2, sdim*2, fill=255)\n",
" mask1 = cv2.drawContours(mask1, [biggestcontour], -1, 0, thickness=cv2.FILLED)\n",
" \n",
" \n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_DILATE, kernelell, iterations=2)\n",
" \n",
" \n",
" # mask1 = mask1[(sdim*2):-(sdim*2), (sdim*2):-(sdim*2)]\n",
" # return mask1\n",
" \n",
" # morphed2l = mf.padWithColour(morphedl, sdim*2, sdim*2, fill=255)\n",
" morphed2l = cv2.morphologyEx(morphedl, cv2.MORPH_OPEN, kernel, iterations=1)\n",
" # morphed2l = morphed2l[(sdim*2):-(sdim*2), (sdim*2):-(sdim*2)]\n",
" \n",
" # return morphed2l\n",
" # print(mask1.shape)\n",
" # print(morphed2l.shape)\n",
" morphed2l = cv2.bitwise_or(morphed2l, 255-mask1)\n",
" # return morphed2l\n",
" \n",
" morphed2l = morphed2l[(sdim*2):-(sdim*2), (sdim*2):-(sdim*2)]\n",
" temp_final = cv2.bitwise_or(threshl, 255-morphed2l)\n",
" return temp_final\n",
" \n",
" canny = cv2.Canny(morphed2l, 0, 500)\n",
" # return canny\n",
"\n",
" minlength = max(mainimage.shape[0], mainimage.shape[1])//7\n",
" mingap = max(mainimage.shape[0], mainimage.shape[1])//20\n",
" linesP = cv2.HoughLinesP(canny, 1, np.pi / 180, 30, None, minlength, mingap)\n",
" vminlength = mainimage.shape[0]//10\n",
" vmaxgap = mainimage.shape[0]//50\n",
" vlinesP = cv2.HoughLinesP(canny, 1, np.pi / 180, 10, None, vminlength, vmaxgap)\n",
" \n",
" hminlength = mainimage.shape[1]//15\n",
" hmaxgap = mainimage.shape[1]//40\n",
" hlinesP = cv2.HoughLinesP(canny, 1, np.pi / 180, 10, None, hminlength, hmaxgap)\n",
" # print(linesP)\n",
" \n",
" vmarginlines = mf.WithinXDegrees(linesP, 10)\n",
" hmarginlines = mf.WithinXDegrees(linesP, 10, baseangle=90)\n",
" vmarginlines = mf.WithinXDegrees(vlinesP, 15)\n",
" hmarginlines = mf.WithinXDegrees(hlinesP, 15, baseangle=90)\n",
" \n",
" marginlines = np.append(vmarginlines, hmarginlines, axis=0)\n",
" # marginlines = marginlines.astype(int)\n",
" # # print(marginlines)\n",
" # reshaped = np.reshape(marginlines, (-1,1, 2))\n",
" # # reshaped = cv2.convexHull(reshaped)\n",
" # # print(reshaped)\n",
" \n",
" # colourdst = cv2.cvtColor(morphedl, cv2.COLOR_GRAY2BGR)\n",
" # if marginlines is not None:\n",
" # for l in marginlines:\n",
" # cv2.line(colourdst, (int(l[0]), int(l[1])), (int(l[2]), int(l[3])), (0,0,255), 3, cv2.LINE_AA)\n",
" # return colourdst\n",
" \n",
" \n",
" colourdst = cv2.cvtColor(morphedl, cv2.COLOR_GRAY2BGR)\n",
" # out = cv2.drawContours(colourdst, [reshaped], -1, (0,255,0), thickness=3)\n",
" # return out\n",
" \n",
" \n",
" #### NEW IDEA: MERGE THE WHITEOUT BACKGROUND AND TEXT CLARIFICATION STEP BECAUSE DOING THE OTSU THRESHOLD SEEMS TO WORK PRETTY WELL AND IF I JUST WHITE OUT THE OUTER AREA (ACTUALLY WHITE)\n",
" # THEN I HAVE JUST THE TEXT\n",
" \n",
"\n",
" if marginlines is not None:\n",
" for l in marginlines:\n",
" cv2.line(colourdst, (int(l[0]), int(l[1])), (int(l[2]), int(l[3])), (0,0,255), 3, cv2.LINE_AA)\n",
" return colourdst\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" ## IDEA:\n",
" # MASK OUT THE WORDS USING OUR MASKS MADE FROM THE STUFF BELOW. THEN WHEN CANNY IS DONE TO IT, IT SHOULDN'T HAVE A WHOLE BUNCH OF SHIT IN THE CENTER. STILL NEED TO FIGURE OUT HOW TO LINK THE HOUGH LINES AROUND THE RECEIPT\n",
"\n",
"\n",
"\n",
"\n",
"\n",
" # morphedl = 255-cv2.morphologyEx(255-threshl, cv2.MORPH_OPEN, kernel, iterations=3)\n",
" morphedl = paddedl\n",
@ -184,7 +258,8 @@
" # return morphedl\n",
" \n",
" contours, heirarchy = cv2.findContours(morphedl, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" print(contours)\n",
" # print(contours[0].shape)\n",
" print(contours[0])\n",
" biggestcontour = max(contours, key=cv2.contourArea)\n",
" return canny\n",
" \n",
@ -253,418 +328,161 @@
" \n",
" imgout = cv2.drawContours(mainimage, contours, -1, (0,255,0), thickness=3)\n",
" return imgout\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" blurimagel = cv2.blur(labl, (7,7))\n",
" blurimagea = cv2.blur(laba, (7,7))\n",
" blurimageb = cv2.blur(labb, (7,7))\n",
" \n",
" \n",
" window = lab.shape[1]//5\n",
" if window % 2 == 0:\n",
" window += 1\n",
" threshl = 255-cv2.adaptiveThreshold(blurimagel, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 2)\n",
" window = lab.shape[1]//3\n",
" if window % 2 == 0:\n",
" window += 1\n",
" thresha = cv2.adaptiveThreshold(blurimagea, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 0)\n",
" window = lab.shape[1]//10\n",
" if window % 2 == 0:\n",
" window += 1\n",
" threshb = cv2.adaptiveThreshold(blurimageb, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 0)\n",
" # return threshl\n",
" # imglist.append(threshl)\n",
" # imglist.append(thresha)\n",
" # imglist.append(threshb)\n",
" # threshmerge = cv2.bitwise_or(thresha, threshb)\n",
" # imglist.append(threshmerge)\n",
" # threshmerge = cv2.bitwise_or(threshl, threshmerge)\n",
" # imglist.append(threshmerge)\n",
" # return imglist\n",
" # return threshmerge\n",
" threshmerge = threshl\n",
" \n",
" dim = int(min(threshmerge.shape[0], threshmerge.shape[1])/100)\n",
" # dim = 2\n",
" # dim = dotsize\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" \n",
" padthresh = mf.padWithColour(threshmerge, sdim*2, sdim*2, fill=255)\n",
" mask1t = cv2.morphologyEx(padthresh, cv2.MORPH_OPEN, kernel, iterations=1)\n",
" # mask1t = cv2.morphologyEx(mask1t, cv2.MORPH_OPEN, skernel)\n",
" # imglist.append(mask1t)\n",
" # return mask1t\n",
" \n",
" contours, heirarchy = cv2.findContours(255-mask1t, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" biggestcontour = max(contours, key=cv2.contourArea)\n",
" \n",
" blank = np.full(threshmerge.shape, 255, dtype=np.uint8)\n",
" mask1 = blank.copy()\n",
" mask1 = mf.padWithColour(mask1, sdim*2, sdim*2, fill=255)\n",
" mask1 = cv2.drawContours(mask1, [biggestcontour], -1, 0, thickness=cv2.FILLED)\n",
" # temp = cv2.drawContours(image, [biggestcontour], -1, 255, thickness=3)\n",
" # imglist.append(temp)\n",
" # imglist.append(mask1)\n",
" # return mask1\n",
" \n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=2)\n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=1)\n",
" # return mask1\n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=2)\n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, skernel, iterations=1)\n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=2)\n",
" mask1 = mask1[(sdim*2):-(sdim*2), (sdim*2):-(sdim*2)]\n",
" # imglist.append(mask1)\n",
" # return mask1\n",
" \n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_DILATE, kernel)\n",
" \n",
" # resizemask = cv2.resize(mask1, (ogshape[1], ogshape[0]))\n",
" resizemask = mask1\n",
" # return resizemask\n",
" maskc = cv2.cvtColor(resizemask, cv2.COLOR_GRAY2BGR)\n",
" # print(maskc.shape)\n",
" # print(image.shape)\n",
" whitedbackground = cv2.bitwise_or(shrunkimg, maskc)\n",
" # imglist.append(whitedbackground)\n",
" # return whitedbackground\n",
" \n",
" test = cv2.inpaint(whitedbackground, resizemask, 3, cv2.INPAINT_TELEA)\n",
" # return test\n",
" # if (test.shape[1] > test.shape[0]):\n",
" # shrunktest = mf.ResizeWithAspectRatio(image, width=shrunkdim)\n",
" # else:\n",
" # shrunktest = mf.ResizeWithAspectRatio(image, height=shrunkdim)\n",
" \n",
" sdim = int(min(mainimage.shape[0], mainimage.shape[1])/40)\n",
" srkernel = cv2.getStructuringElement(cv2.MORPH_RECT, (sdim, sdim))\n",
" skernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (sdim, sdim))\n",
" \n",
" \n",
" lab2 = cv2.cvtColor(test, cv2.COLOR_BGR2LAB)\n",
" lab2l = lab2[:,:,0]\n",
" lab2a = lab2[:,:,1]\n",
" lab2b = lab2[:,:,2]\n",
" blurimage2l = cv2.blur(lab2l, (3,3))\n",
" # blurimage2l = lab2l\n",
" \n",
" # window = lab.shape[1]//10\n",
" # if window % 2 == 0:\n",
" # window += 1\n",
" # thresh2l = 255-cv2.adaptiveThreshold(blurimage2l, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 0)\n",
" thresh2l = cv2.threshold(blurimage2l, 0, 255, cv2.THRESH_OTSU)[1]\n",
" \n",
" morphed2l = 255-cv2.morphologyEx(255-thresh2l, cv2.MORPH_OPEN, kernel, iterations=3)\n",
" padded2l = mf.padWithColour(morphed2l, sdim*2, sdim*2, fill=0)\n",
" \n",
" mask2 = cv2.morphologyEx(padded2l, cv2.MORPH_OPEN, srkernel)\n",
" # mask2 = padded2l\n",
" \n",
" mask2 = 255-mask2[(sdim*2):-(sdim*2), (sdim*2):-(sdim*2)]\n",
" \n",
" ##IT'S GOOD HERE. NOW, I CAN IMPLEMENT THE SHRINKING AGAIN, ADD PADDING, MORPHOLOGY TO CONNECT THE SHIT TO THE EDGE, AND THEN GET THE BIGGEST CONTOUR AGAIN\n",
" ## shrinking part \"implemented\" (it wasn't expanded to begin with), the padding and morphology+ still needs to be done\n",
" # return mask2\n",
"\n",
" mask2c = cv2.cvtColor(mask2, cv2.COLOR_GRAY2BGR)\n",
" whitedbackground = cv2.bitwise_or(test, mask2c)\n",
" return whitedbackground\n",
"\n",
" \n",
" return imglist\n",
" \n",
" \n",
" \n",
" imagecpy = image.copy()\n",
" blurimage = cv2.blur(imagecpy, (13,13))\n",
" \n",
"\n",
" \n",
" \n",
" # ogcover = np.full(imagecpy.shape, 0, dtype=np.uint8)\n",
" # ogcover = mf.padWithColour(ogcover, sdim, sdim, fill=(255,255,255))\n",
" # ogcover = cv2.cvtColor(ogcover, cv2.COLOR_BGR2GRAY)\n",
" \n",
" # blurimage = mf.padWithColour(blurimage, sdim, sdim, fill=(255,255,255))\n",
" # imagecpy = cv2.inpaint(blurimage, ogcover, 3, cv2.INPAINT_TELEA)\n",
" # imagecpy = cv2.copyMakeBorder(blurimage, sdim, sdim, sdim, sdim, cv2.BORDER_REPLICATE)\n",
" # return imagecpy\n",
" # imagecpy = mf.padWithColour(image, hpadding=sdim, vpadding=sdim)\n",
" \n",
" lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)\n",
" gray = lab[:,:,0]\n",
" # gray = cv2.cvtColor(blurimage, cv2.COLOR_BGR2GRAY)\n",
" \n",
" # blur = cv2.blur(gray, (7,7))\n",
" \n",
" # window = 51\n",
" window = gray.shape[1]//7\n",
" if window % 2 == 0:\n",
" window += 1\n",
" thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 2)\n",
" # thresh2 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)[1]\n",
" # thresh = cv2.bitwise_and(thresh1, thresh2)\n",
" # return thresh\n",
" \n",
" # initialcontours, heirarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" \n",
" # contourrects = np.array([list(cv2.boundingRect(contour)) for contour in initialcontours])\n",
" # rectdims = contourrects[:,2:]\n",
" # flatrectdims = rectdims.flatten()\n",
" # dotsize = int(np.median(flatrectdims)//2)\n",
" # # print(contourrects)\n",
" # # print(rectdims)\n",
" # # print(dotsize)\n",
" \n",
" \n",
"\n",
" # dim = int(min(thresh.shape[0], thresh.shape[1])/400)\n",
" dim = 2\n",
" # dim = dotsize\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" morphedthresh = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel)\n",
" return morphedthresh\n",
" \n",
" \n",
" contours, heirarchy = cv2.findContours(morphedthresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" biggestcontour = max(contours, key=cv2.contourArea)\n",
" \n",
" \n",
" # epsilon = 0.0005*cv2.arcLength(biggestcontour,True)\n",
" # approx = cv2.approxPolyDP(biggestcontour,epsilon,True)\n",
" \n",
" blank = np.full(thresh.shape, 255, dtype=np.uint8)\n",
" mask1 = 255 - blank.copy()\n",
" mask1 = cv2.drawContours(mask1, [biggestcontour], -1, 255, thickness=cv2.FILLED)\n",
" \n",
" mask1 = mf.padWithColour(mask1, sdim, sdim, fill=0)\n",
" \n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=1)\n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, skernel, iterations=1)\n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, skernel)\n",
" # return mask1\n",
" \n",
" \n",
" mask1contours, heirarchy = cv2.findContours(mask1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" \n",
" biggestm1contour = max(mask1contours, key=cv2.contourArea)\n",
" \n",
" mask1_1 = 255-blank.copy()\n",
" mask1_1 = mf.padWithColour(mask1_1, sdim, sdim, fill=0)\n",
" mask1_1 = cv2.drawContours(mask1_1, [biggestm1contour], -1, 255, thickness=cv2.FILLED)\n",
" mask1_1 = 255-mask1_1\n",
" \n",
" dim = max(2,int(min(image.shape[0], image.shape[1])/100))\n",
" # print(dim)\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" mask1_1 = cv2.morphologyEx(mask1_1, cv2.MORPH_DILATE, kernel, iterations=1)\n",
" mask1_1 = mask1_1[sdim:-sdim, sdim:-sdim]\n",
" \n",
" # epsilon = 0.01*cv2.arcLength(biggestm1contour,True)\n",
" # approxm1 = cv2.approxPolyDP(biggestm1contour,epsilon,True)\n",
" \n",
" # hull = cv2.convexHull(biggestcontour)\n",
" # hull = cv2.convexHull(approx)\n",
" # mask2 = 255 - blank.copy()\n",
" # mask2 = cv2.drawContours(mask2, [hull], -1, 255, thickness=cv2.FILLED)\n",
" \n",
" # imagecpy = cv2.drawContours(imagecpy, [biggestcontour], -1, (255,0,0), thickness=3)\n",
" # # imagecpy = cv2.drawContours(imagecpy, [approx], -1, (0,255,0), thickness=3)\n",
" # # imagecpy = cv2.drawContours(imagecpy, [hull], -1, (0,255,255), thickness=3)\n",
" # imagecpy = cv2.drawContours(imagecpy, [biggestm1contour], -1, (0,0,255), thickness=3)\n",
" # # imagecpy = cv2.drawContours(imagecpy, [approxm1], -1, (255,0,255), thickness=3)\n",
" # return imagecpy\n",
" \n",
" # mask = 255 - cv2.bitwise_and(mask1, mask2)\n",
" # return mask1_1\n",
" \n",
" maskc = cv2.cvtColor(mask1_1, cv2.COLOR_GRAY2BGR)\n",
" # return maskc\n",
" # return blurimage\n",
" # print(blurimage)\n",
" # print(maskc)\n",
" whitedbackground = cv2.bitwise_or(image, maskc)\n",
" return whitedbackground\n",
"\n",
"\n",
"\n",
"\n",
"##### NEED TO FIX THE CURVE OF CONNECTING TO THE EDGES DUE TO THE ELLIPSE KERNEL\n",
" \n",
" graywhitedbackground = cv2.cvtColor(whitedbackground, cv2.COLOR_BGR2GRAY)\n",
" # thresh2 = cv2.threshold(graywhitedbackground, 0, 255, cv2.THRESH_OTSU)[1]\n",
" blurredgraywhitedbackground = cv2.blur(graywhitedbackground, (11,11))\n",
" # blurredgraywhitedbackground = graywhitedbackground\n",
" window = blurredgraywhitedbackground.shape[1]//15\n",
" if window % 2 == 0:\n",
" window += 1\n",
" thresh2 = cv2.adaptiveThreshold(blurredgraywhitedbackground, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 2)\n",
" # return thresh2\n",
" \n",
" paddedthresh2 = mf.padWithColour(thresh2, sdim, sdim, fill=255)\n",
" \n",
" \n",
" dim = max(2,int(min(image.shape[0], image.shape[1])/50))\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" t2morph = cv2.morphologyEx(paddedthresh2, cv2.MORPH_OPEN, kernel, iterations=2)\n",
" dim = int(window*1.5)\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" t2morph = cv2.morphologyEx(t2morph, cv2.MORPH_CLOSE, kernel, iterations=1)\n",
" \n",
" t2morph = t2morph[sdim:-sdim, sdim:-sdim]\n",
" # return t2morph\n",
"\n",
" # print(mask1_1.shape)\n",
" # print(t2morph.shape)\n",
" mask2 = 255-cv2.bitwise_or(mask1_1, 255-t2morph)\n",
" # return mask2\n",
" \n",
" \n",
" \n",
" mask2contours, heirarchy = cv2.findContours(mask2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" \n",
" biggestm2contour = max(mask2contours, key=cv2.contourArea)\n",
" \n",
" mask2_1 = 255 - blank.copy()\n",
" mask2_1 = cv2.drawContours(mask2_1, [biggestm2contour], -1, 255, thickness=cv2.FILLED)\n",
" \n",
" # return mask2_1\n",
" \n",
" mask2_1 = mf.padWithColour(mask2_1, sdim, sdim, fill=0)\n",
" \n",
" mask2_2 = cv2.morphologyEx(mask2_1, cv2.MORPH_OPEN, kernel)\n",
" \n",
" mask2_2 = 255-mask2_2[sdim:-sdim, sdim:-sdim]\n",
" \n",
" # return mask2_2\n",
"\n",
" mask2c = cv2.cvtColor(mask2_2, cv2.COLOR_GRAY2BGR)\n",
" # return maskc\n",
" # return blurimage\n",
" # print(blurimage)\n",
" # print(maskc)\n",
" whitedbackground2 = cv2.bitwise_or(image, mask2c)\n",
" return whitedbackground2\n",
" \n",
" \n",
" \n",
" \n",
" canny = cv2.Canny(graywhitedbackground, 0, 500)\n",
" return canny\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" contours1, heirarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" contours2, heirarchy = cv2.findContours(morphedthresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" \n",
"\n",
"\n",
" biggestcontour2 = max(contours1, key=cv2.contourArea)\n",
" biggestcontour1 = max(contours2, key=cv2.contourArea)\n",
" \n",
" epsilon = 0.0005*cv2.arcLength(biggestcontour1,True)\n",
" approx = cv2.approxPolyDP(biggestcontour1,epsilon,True)\n",
" # approx = cv2.convexHull(approx)\n",
" epsilon = 0.005*cv2.arcLength(approx,True)\n",
" approx = cv2.approxPolyDP(approx,epsilon,True)\n",
" # approx = cv2.convexHull(biggestcontour1)\n",
" # print(approx)\n",
" \n",
" imagecpy = cv2.drawContours(imagecpy, [biggestcontour1], -1, (0,255,0), thickness=3)\n",
" imagecpy = cv2.drawContours(imagecpy, [biggestcontour2], -1, (0,0,255), thickness=3)\n",
" \n",
" imagecpy = cv2.drawContours(imagecpy, [approx], -1, (255,0,0), thickness=3)\n",
" # return imagecpy\n",
" \n",
" blank = np.full(thresh.shape, 255, dtype=np.uint8)\n",
" mask = blank.copy()\n",
" mask = cv2.drawContours(mask, [biggestcontour1], -1, (0,0,0), thickness=cv2.FILLED)\n",
" # mask = cv2.drawContours(mask, [approx], -1, (0,0,0), thickness=cv2.FILLED)\n",
" # mask = cv2.drawContours(mask, [biggestcontour2], -1, (0,0,0), thickness=cv2.FILLED)\n",
"\n",
" # return mask\n",
"\n",
" invertmask = 255 - mask\n",
" \n",
" \n",
" dim = int(min(invertmask.shape[0], invertmask.shape[1])/200)\n",
" # # dim = 21\n",
" # print(dim)\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" # invertmask = cv2.morphologyEx(invertmask, cv2.MORPH_DILATE, kernel)\n",
" mask = 255 - cv2.morphologyEx(invertmask, cv2.MORPH_ERODE, kernel, iterations=1)\n",
" return mask\n",
" \n",
" maskcontours, heirarchy = cv2.findContours(255-mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" \n",
" mainmaskcontour = max(maskcontours, key=cv2.contourArea)\n",
" mask1 = blank.copy()\n",
" mask1 = cv2.drawContours(mask1, [mainmaskcontour], -1, (0,0,0), thickness=cv2.FILLED)\n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_ERODE, kernel, iterations=1)\n",
" # temp = cv2.drawContours(image, [mainmaskcontour], -1, (0,255,0), thickness=3)\n",
" # return temp\n",
" \n",
" mask1c = cv2.cvtColor(mask1, cv2.COLOR_GRAY2BGR)\n",
" whitedbackground = cv2.bitwise_or(image, mask1c)\n",
" # return whitedbackground\n",
" \n",
" mask2 = blank.copy()\n",
" mask2 = 255-cv2.drawContours(mask2, [approx], -1, (0,0,0), thickness=cv2.FILLED)\n",
" \n",
" dim = int(min(mask2.shape[0], mask2.shape[1])/50)\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" morphedmask = 255-cv2.morphologyEx(mask2, cv2.MORPH_OPEN, kernel, iterations=7)\n",
" # return morphedmask\n",
" \n",
" finalmask = cv2.bitwise_or(mask1, morphedmask)\n",
" \n",
" \n",
" finalmaskbgr = cv2.cvtColor(finalmask, cv2.COLOR_GRAY2BGR)\n",
" # return finalmaskbgr\n",
"\n",
" whitedbackground = cv2.bitwise_or(whitedbackground, finalmaskbgr)\n",
" # return whitedbackground\n",
" \n",
" test = cv2.inpaint(whitedbackground, finalmask, 3, cv2.INPAINT_TELEA)\n",
" return test"
" \n"
]
},
{
"cell_type": "code",
"execution_count": 1901,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"def textleaver(image):\n",
" ogshape = image.shape\n",
" shrunkdim=1000\n",
" if (image.shape[1] > image.shape[0]):\n",
" shrunkimg, scaler = mf.ResizeWithAspectRatio(image, width=shrunkdim, retscale=True)\n",
" else:\n",
" shrunkimg, scaler = mf.ResizeWithAspectRatio(image, height=shrunkdim, retscale=True)\n",
" \n",
" mainimage = shrunkimg\n",
" \n",
" sdim = int(min(mainimage.shape[0], mainimage.shape[1])/5)\n",
" srkernel = cv2.getStructuringElement(cv2.MORPH_RECT, (sdim, sdim))\n",
" skernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (sdim, sdim))\n",
" \n",
" oglab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)\n",
" lab = cv2.cvtColor(mainimage, cv2.COLOR_BGR2LAB)\n",
" \n",
" imglist = []\n",
" # imglist.append(mainimage)\n",
" \n",
" labl = lab[:,:,0]\n",
" oglabl = oglab[:,:,0]\n",
" # # imglist.append(labl)\n",
" # # imglist.append(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY))\n",
" # laba = lab[:,:,1]\n",
" # # imglist.append(laba)\n",
" # labb = lab[:,:,2]\n",
" # # imglist.append(labb)\n",
" \n",
" divisor = 1.5\n",
" window = int(min(labl.shape)/divisor)\n",
" window = window if window%2 == 1 else window + 1\n",
" # canny = cv2.Canny(labl, 0, 500)\n",
" ethreshl = cv2.threshold(labl, 0, 255, cv2.THRESH_OTSU)[1]\n",
" threshl = cv2.threshold(labl, 0, 255, cv2.THRESH_OTSU)[1]\n",
" # threshl = cv2.adaptiveThreshold(labl, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 35)\n",
" \n",
" \n",
" ogwindow = int(min(oglabl.shape)/divisor)\n",
" ogwindow = window if window%2 == 1 else window + 1\n",
" print(ogwindow)\n",
" ogthreshl = cv2.threshold(oglabl, 0, 255, cv2.THRESH_TRIANGLE)[1]\n",
" return ogthreshl\n",
" # ogthreshl = cv2.adaptiveThreshold(oglabl, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, ogwindow, 35)\n",
" # return threshl\n",
" \n",
" colourthresh = cv2.cvtColor(threshl, cv2.COLOR_GRAY2BGR)\n",
" \n",
" dim = int(min(mainimage.shape[0], mainimage.shape[1])/100)\n",
" # dim = 2\n",
" # dim = dotsize\n",
" dim = max(3,dim)\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" kernelell = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (dim, dim))\n",
" \n",
" # paddedl = mf.padWithColour(threshl, sdim*2, sdim*2, fill=0)\n",
" paddedl = threshl\n",
" # return paddedl\n",
" \n",
" \n",
" # morphedl = 255-cv2.morphologyEx(255-threshl, cv2.MORPH_OPEN, kernel, iterations=3)\n",
" morphedl = paddedl\n",
" morphed1l = cv2.morphologyEx(morphedl, cv2.MORPH_ERODE, kernel, iterations=1)\n",
" # morphed1l = cv2.morphologyEx(morphed1l, cv2.MORPH_OPEN, kernel, iterations=1)\n",
" # morphed1l = cv2.morphologyEx(morphed1l, cv2.MORPH_OPEN, kernel, iterations=1)\n",
" # morphed1l = cv2.morphologyEx(morphedl, cv2.MORPH_ERODE, kernelell, iterations=2)\n",
" \n",
" emorphed1l = cv2.morphologyEx(ethreshl, cv2.MORPH_ERODE, kernel, iterations=1)\n",
"\n",
" # return morphedl\n",
" \n",
" contours, heirarchy = cv2.findContours(morphed1l, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" biggestcontour = max(contours, key=cv2.contourArea)\n",
" \n",
" # temp = cv2.drawContours(colourthresh, [biggestcontour], -1, (0,255,0), thickness=1)\n",
" # return temp\n",
" \n",
" \n",
" blank = np.full(labl.shape, 255, dtype=np.uint8)\n",
" mask1 = blank.copy()\n",
" # mask1 = mf.padWithColour(mask1, sdim*2, sdim*2, fill=255)\n",
" mask1 = cv2.drawContours(mask1, [biggestcontour], -1, 0, thickness=cv2.FILLED)\n",
" ## need to change the erosion so that if the paper goes to the edge, it doesn't get eroded in (because that means the paper is right to the edge and writing may be close)\n",
" \n",
" contours, heirarchy = cv2.findContours(morphed1l, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
" biggestcontour = max(contours, key=cv2.contourArea)\n",
" \n",
" emask1 = blank.copy()\n",
" emask1 = cv2.drawContours(emask1, [biggestcontour], -1, 0, thickness=cv2.FILLED)\n",
" \n",
" mask1 = 255-cv2.morphologyEx(255-mask1, cv2.MORPH_ERODE, kernel, iterations=2)\n",
" \n",
" emask1 = 255-cv2.morphologyEx(255-emask1, cv2.MORPH_ERODE, kernel, iterations=2)\n",
" \n",
" \n",
" # mask1 = mask1[(sdim*2):-(sdim*2), (sdim*2):-(sdim*2)]\n",
" # return mask1\n",
" \n",
" # morphed2l = mf.padWithColour(morphedl, sdim*2, sdim*2, fill=255)\n",
" morphed2l = cv2.morphologyEx(morphedl, cv2.MORPH_OPEN, kernel, iterations=1)\n",
" morphed2l = cv2.morphologyEx(morphedl, cv2.MORPH_ERODE, kernel, iterations=1)\n",
" # morphed2l = morphed2l[(sdim*2):-(sdim*2), (sdim*2):-(sdim*2)]\n",
" \n",
" # return morphed2l\n",
" # print(mask1.shape)\n",
" # print(morphed2l.shape)\n",
" morphed2l = cv2.bitwise_or(morphed2l, 255-mask1)\n",
" # return morphed2l\n",
"\n",
" # paddedthreshl = mf.padWithColour(morphed2l, sdim*2, sdim*2, fill=255)\n",
" # temp = cv2.drawContours(colourthresh, [biggestcontour], -1, (0,255,0), thickness=1)\n",
" # return temp\n",
"\n",
"\n",
" morphed2l = cv2.morphologyEx(morphed2l, cv2.MORPH_ERODE, kernel, iterations=1)\n",
" morphed2l = cv2.morphologyEx(morphed2l, cv2.MORPH_ERODE, kernelell, iterations=1)\n",
" # return morphed2l\n",
" # morphed2l = cv2.bitwise_or(morphed2l, 255-emask1)\n",
" \n",
" # morphed2l = morphed2l[(sdim*2):-(sdim*2), (sdim*2):-(sdim*2)]\n",
" \n",
" resizedmask = cv2.resize(255-morphed2l, (ogshape[1], ogshape[0]))\n",
" temp_final = cv2.bitwise_or(ogthreshl, resizedmask)\n",
" \n",
" dim=3\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (dim, dim))\n",
" temp_final = cv2.morphologyEx(temp_final, cv2.MORPH_OPEN, kernel)\n",
" temp_final = cv2.morphologyEx(temp_final, cv2.MORPH_OPEN, kernel)\n",
" # temp_final = cv2.morphologyEx(temp_final, cv2.MORPH_CLOSE, kernel)\n",
" # temp_final = cv2.morphologyEx(temp_final, cv2.MORPH_OPEN, kernel)\n",
" return temp_final"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"def cropclarifying(image):\n",
" whitedbackground = whiteoutbackground(image)\n",
" return whitedbackground\n",
" # whitedbackground = whiteoutbackground(image)\n",
" # return whitedbackground\n",
"\n",
" textrefined = mf.textClarifying(whitedbackground)\n",
" # return textrefined\n",
" # textrefined = mf.textClarifying(whitedbackground)\n",
" textrefined = textleaver(image)\n",
" return textrefined\n",
" #maybe now is when I put in the line removing function\n",
"\n",
" lineout = mf.removeLinesFromText(textrefined)\n",
@ -675,7 +493,7 @@
},
{
"cell_type": "code",
"execution_count": 1902,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
@ -684,15 +502,18 @@
" # return croppedanddeskewed\n",
" \n",
" \n",
" postprocessed = cropclarifying(croppedanddeskewed)\n",
" return postprocessed\n",
" postprocessed = mf.croptoblack(postprocessed)\n",
" # postprocessed = cropclarifying(croppedanddeskewed)\n",
" postprocessed = croppedanddeskewed\n",
" # return postprocessed\n",
" # postprocessed = mf.croptoblack(postprocessed)\n",
" \n",
" # postprocessed = cv2.cvtColor(postprocessed, cv2.COLOR_GRAY2BGR)\n",
" # return postprocessed\n",
" \n",
" # final = mf.externaldeskew(postprocessed, fill=(255,255,255))\n",
" final = mf.receipttextdeskew(postprocessed, fill=(255,255,255))\n",
" # rotangle = mf.receipttextdeskew(postprocessed, fill=(255,255,255), returnangle=True)\n",
" final = postprocessed\n",
" \n",
" \n",
" # final = mf.croptoblack(final)\n",
" \n",
@ -706,7 +527,7 @@
},
{
"cell_type": "code",
"execution_count": 1903,
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
@ -715,9 +536,17 @@
},
{
"cell_type": "code",
"execution_count": 1904,
"execution_count": 11,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"0.0\n"
]
}
],
"source": [
"# prepped, scaler, hp, vp = mf.squareandthenresize(img, fill=255, width=1000, returnscalerinfo=True)\n",
"outs = houghlineprocessing(img)\n",
@ -731,7 +560,7 @@
},
{
"cell_type": "code",
"execution_count": 1905,
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
@ -745,7 +574,7 @@
},
{
"cell_type": "code",
"execution_count": 1906,
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
@ -757,7 +586,7 @@
},
{
"cell_type": "code",
"execution_count": 1907,
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
@ -766,7 +595,7 @@
},
{
"cell_type": "code",
"execution_count": 1908,
"execution_count": 15,
"metadata": {},
"outputs": [],
"source": [
@ -776,7 +605,7 @@
},
{
"cell_type": "code",
"execution_count": 1909,
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
@ -806,14 +635,30 @@
},
{
"cell_type": "code",
"execution_count": 1910,
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"average time: 0.20301511883735657(s)\n"
"0.9740282517223996\n",
"-2.0053522829578814\n",
"-0.9740282517223996\n",
"0.0\n",
"0.9740282517223996\n",
"-0.9740282517223996\n",
"-0.011669615052326776\n",
"2.0053522829578814\n",
"0.0\n",
"0.0\n",
"0.0\n",
"-2.979380534680281\n",
"0.0\n",
"0.0\n",
"-2.0053522829578814\n",
"-11.000789666511807\n",
"average time: 0.19967518746852875(s)\n"
]
}
],
@ -824,7 +669,7 @@
},
{
"cell_type": "code",
"execution_count": 1911,
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
@ -834,7 +679,7 @@
},
{
"cell_type": "code",
"execution_count": 1912,
"execution_count": 19,
"metadata": {},
"outputs": [],
"source": [
@ -843,7 +688,7 @@
},
{
"cell_type": "code",
"execution_count": 1913,
"execution_count": 20,
"metadata": {},
"outputs": [],
"source": [

View File

@ -507,6 +507,19 @@ def houghlinedeskewandcrop(image):
## -----------------finding angle to deskew-----------------
rotationangle = houghlinedeskewangle(croppedcanny)
# print(croppedcanny.shape)
# print(abs(rotationangle))
if (croppedcanny.shape[0] > croppedcanny.shape[1]):
if (rotationangle > 45):
rotationangle -= 90
elif rotationangle < -45:
rotationangle += 90
# print(rotationangle)
# elif (croppedcanny.shape[1] > croppedcanny.shape[0]):
# if (rotationangle > 45):
# rotationangle -= 90
# elif rotationangle < -45:
# rotationangle += 90
# print(rotationangle)
@ -1117,26 +1130,41 @@ def getreceipttextAngle(cvImage) -> float:
# print(angle)
return angle
def receipttextdeskew(img, fill=(0,0,0)):
def receipttextdeskew(img, fill=(0,0,0), returnangle=False):
colourimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
angle = getreceipttextAngle(colourimg)
padimg = padWithColour(img, hpadding=50, vpadding=50, fill=fill)
rotated = rotate(padimg, angle, fill=fill)
if returnangle:
return angle
# padimg = padWithColour(img, hpadding=50, vpadding=50, fill=fill)
# print(img.shape)
# grayfill = int((fill[0]*0.299) + (fill[1]*0.587) + (fill[2]*0.114))
rotated = rotatewithexactpadding(colourimg, angle, fill=fill)
grayrotated = cv2.cvtColor(rotated, cv2.COLOR_BGR2GRAY)
# print(grayrotated)
croprect = croptoblack(grayrotated, returnrect=True)
# rotated = cv2.cvtColor(rotated, cv2.COLOR_GRAY2BGR)
rotated = rotated[croprect[1]:croprect[1]+croprect[3], croprect[0]:croprect[0]+croprect[2], :]
rotated = padWithColour(rotated, hpadding=50, vpadding=50, fill=fill)
return rotated
## ------------------------------Full deskewing and cropping------------------------------
def houghlineprocessing(image):
croppedanddeskewed, angle = houghlinedeskewandcrop(image)
croppedanddeskewed, angle = mf.houghlinedeskewandcrop(image)
# return croppedanddeskewed
postprocessed = cropclarifying(croppedanddeskewed)
# postprocessed = cropclarifying(croppedanddeskewed)
postprocessed = croppedanddeskewed
# return postprocessed
postprocessed = croptoblack(postprocessed)
# postprocessed = mf.croptoblack(postprocessed)
# postprocessed = cv2.cvtColor(postprocessed, cv2.COLOR_GRAY2BGR)
# return postprocessed
# final = mf.externaldeskew(postprocessed, fill=(255,255,255))
final = receipttextdeskew(postprocessed, fill=(255,255,255))
# rotangle = mf.receipttextdeskew(postprocessed, fill=(255,255,255), returnangle=True)
final = postprocessed
# final = mf.croptoblack(final)