Compare commits

...

1 Commits

Author SHA1 Message Date
ae2e6366e1 Updating line isolator to work better with TrOCR model
Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
2023-11-14 13:30:54 -05:00
4 changed files with 118 additions and 141 deletions

View File

@ -520,22 +520,11 @@ def ismultiline(img):
def lineisolator(image):
# imgcopy = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# thresholded = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# return gray
# return thresholded
thresholded = gray
# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
lineimages = lineimagemaker(thresholded, 1.5, False)
# for i, lineimage in enumerate(lineimages):
# lineimages[i] = cv2.morphologyEx(lineimage, cv2.MORPH_ERODE, kernel)
finallineimages = []
for i, lineimage in enumerate(lineimages):
@ -560,25 +549,18 @@ def lineisolator(image):
for i, lineimage in enumerate(finallineimages):
deskewedli = minboxdeskew(lineimage, fill=255)
dim = int((deskewedli.shape[0]-100)//20)
dim = int((deskewedli.shape[0]-90)//20)
# print(dim)
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (dim, dim))
deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_DILATE, kernel,iterations=1)
finallineimages[i] = cv2.morphologyEx(deskewedli, cv2.MORPH_OPEN, kernel)
# mergedboxes, originalboxes = linerectretriever(thresholded)
# mask = np.zeros(thresholded.shape, dtype=np.uint8)
# for i, box in enumerate(mergedboxes):
# for lb in originalboxes[i]:
# mask = cv2.rectangle(mask, (lb[0],lb[1]), (lb[0]+lb[2], lb[1]+lb[3]), (255,255,255), thickness=cv2.FILLED)
ellipsekernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (dim, dim))
rectkernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))
deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_DILATE, rectkernel,iterations=2)
# deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_ERODE, ellipsekernel,iterations=1)
deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_DILATE, ellipsekernel,iterations=1)
deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_ERODE, rectkernel,iterations=1)
# deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_OPEN, ellipsekernel)
# finallineimages[i] = cv2.threshold(deskewedli, 254, 255, cv2.THRESH_BINARY)[1]
finallineimages[i] = deskewedli
# return mask
# out = tempfunc(thresholded)
# return out
return finallineimages

View File

@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
@ -18,20 +18,9 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 24,
"metadata": {},
"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"
]
}
],
"outputs": [],
"source": [
"import sys\n",
"sys.path.insert(0, '../../autocropper')\n",
@ -42,12 +31,12 @@
},
{
"cell_type": "code",
"execution_count": 3,
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"pathname = \"../test_images/\"\n",
"filename = \"IMG_7640.jpg\"\n",
"filename = \"IMG_7605.jpg\"\n",
"# pathname = \"../temp/\"\n",
"# filename = \"test.jpg\"\n",
"# pathname = \"../result_images/\"\n",
@ -59,7 +48,7 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
@ -69,7 +58,7 @@
},
{
"cell_type": "code",
"execution_count": 5,
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
@ -315,8 +304,8 @@
" lineimage = cv2.bitwise_or(whitedscreen, lineimage)[box[1]:box[1]+box[3], box[0]:box[0]+box[2]]\n",
" # lineimage = mf.externaldeskew(lineimage, fill=(255,255,255), alreadygray=True)\n",
" # lineimage = thresholded[box[1]:box[1]+box[3], box[0]:box[0]+box[2]]\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))\n",
" lineimage = cv2.morphologyEx(lineimage, cv2.MORPH_CLOSE, kernel, iterations=1)\n",
" # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))\n",
" # lineimage = cv2.morphologyEx(lineimage, cv2.MORPH_CLOSE, kernel, iterations=1)\n",
" lineimages.append(lineimage)\n",
" # lineimages.append(mask)\n",
" return lineimages\n",
@ -325,29 +314,18 @@
},
{
"cell_type": "code",
"execution_count": 6,
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
"def lineisolator(image):\n",
" # imgcopy = image.copy()\n",
" gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
" # thresholded = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]\n",
" # return gray\n",
" # return thresholded\n",
"\n",
" thresholded = gray\n",
" \n",
" \n",
" # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))\n",
" \n",
" \n",
" \n",
" lineimages = lineimagemaker(thresholded, 1.5, False)\n",
" \n",
" # for i, lineimage in enumerate(lineimages):\n",
" # lineimages[i] = cv2.morphologyEx(lineimage, cv2.MORPH_ERODE, kernel)\n",
"\n",
" \n",
" finallineimages = []\n",
" \n",
" for i, lineimage in enumerate(lineimages):\n",
@ -372,31 +350,24 @@
"\n",
" for i, lineimage in enumerate(finallineimages):\n",
" deskewedli = ef.minboxdeskew(lineimage, fill=255)\n",
" dim = int((deskewedli.shape[0]-100)//20)\n",
" dim = int((deskewedli.shape[0]-90)//20)\n",
" # print(dim)\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (dim, dim))\n",
" deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_DILATE, kernel,iterations=1)\n",
" finallineimages[i] = cv2.morphologyEx(deskewedli, cv2.MORPH_OPEN, kernel)\n",
" \n",
" \n",
" # mergedboxes, originalboxes = linerectretriever(thresholded) \n",
" # mask = np.zeros(thresholded.shape, dtype=np.uint8)\n",
" # for i, box in enumerate(mergedboxes):\n",
" # for lb in originalboxes[i]:\n",
" # mask = cv2.rectangle(mask, (lb[0],lb[1]), (lb[0]+lb[2], lb[1]+lb[3]), (255,255,255), thickness=cv2.FILLED)\n",
" ellipsekernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (dim, dim))\n",
" rectkernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_DILATE, rectkernel,iterations=2)\n",
" # deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_ERODE, ellipsekernel,iterations=1)\n",
" deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_DILATE, ellipsekernel,iterations=1)\n",
" deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_ERODE, rectkernel,iterations=1)\n",
" # deskewedli = cv2.morphologyEx(deskewedli, cv2.MORPH_OPEN, ellipsekernel)\n",
" # finallineimages[i] = cv2.threshold(deskewedli, 254, 255, cv2.THRESH_BINARY)[1]\n",
" finallineimages[i] = deskewedli\n",
"\n",
" # return mask\n",
" \n",
" \n",
" # out = tempfunc(thresholded)\n",
" # return out\n",
" \n",
" return finallineimages"
]
},
{
"cell_type": "code",
"execution_count": 7,
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
@ -405,7 +376,7 @@
},
{
"cell_type": "code",
"execution_count": 8,
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
@ -414,13 +385,13 @@
},
{
"cell_type": "code",
"execution_count": 9,
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"bing = mf.houghlineprocessing(img)\n",
"# outs = bing\n",
"outs = ef.lineisolator(bing)\n",
"outs = lineisolator(bing)\n",
"# # gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
"# # outs = linerectretriever(gray)\n",
"# outs = getSkewAngle(img)\n",
@ -438,7 +409,17 @@
},
{
"cell_type": "code",
"execution_count": 10,
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"# if any(not 255 in x for x in outs[37]):\n",
"# print(\"hi\")"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
@ -447,7 +428,7 @@
},
{
"cell_type": "code",
"execution_count": 11,
"execution_count": 34,
"metadata": {},
"outputs": [],
"source": [
@ -479,11 +460,11 @@
},
{
"cell_type": "code",
"execution_count": 12,
"execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
"# cv2.imwrite(\"../temp/test.jpg\", outs[2])"
"# cv2.imwrite(\"../temp/test.jpg\", outs[37])"
]
}
],

View File

@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 83,
"execution_count": 190,
"metadata": {},
"outputs": [],
"source": [
@ -13,7 +13,7 @@
},
{
"cell_type": "code",
"execution_count": 84,
"execution_count": 191,
"metadata": {},
"outputs": [],
"source": [
@ -21,12 +21,14 @@
"from transformers import VisionEncoderDecoderModel\n",
"\n",
"from PIL import Image\n",
"import torch"
"import torch\n",
"\n",
"torch.cuda.empty_cache()"
]
},
{
"cell_type": "code",
"execution_count": 85,
"execution_count": 192,
"metadata": {},
"outputs": [],
"source": [
@ -40,33 +42,28 @@
},
{
"cell_type": "code",
"execution_count": 86,
"execution_count": 193,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"Could not find image processor class in the image processor config or the model config. Loading based on pattern matching with the model's feature extractor configuration.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Some weights of VisionEncoderDecoderModel were not initialized from the model checkpoint at microsoft/trocr-small-printed and are newly initialized: ['encoder.pooler.dense.bias', 'encoder.pooler.dense.weight']\n",
"Could not find image processor class in the image processor config or the model config. Loading based on pattern matching with the model's feature extractor configuration.\n",
"Some weights of VisionEncoderDecoderModel were not initialized from the model checkpoint at microsoft/trocr-base-stage1 and are newly initialized: ['encoder.pooler.dense.weight', 'encoder.pooler.dense.bias']\n",
"You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.\n"
]
}
],
"source": [
"processor = TrOCRProcessor.from_pretrained('microsoft/trocr-small-printed')\n",
"model = VisionEncoderDecoderModel.from_pretrained('microsoft/trocr-small-printed')"
"modelname = \"microsoft/trocr-base-stage1\"\n",
"processor = TrOCRProcessor.from_pretrained(modelname)\n",
"model = VisionEncoderDecoderModel.from_pretrained(modelname)"
]
},
{
"cell_type": "code",
"execution_count": 87,
"execution_count": 194,
"metadata": {},
"outputs": [],
"source": [
@ -79,17 +76,17 @@
},
{
"cell_type": "code",
"execution_count": 88,
"execution_count": 195,
"metadata": {},
"outputs": [],
"source": [
"filename = \"IMG_7640.jpg\"\n",
"filename = \"IMG_7605.jpg\"\n",
"pathname = \"../test_images/\""
]
},
{
"cell_type": "code",
"execution_count": 89,
"execution_count": 196,
"metadata": {},
"outputs": [],
"source": [
@ -98,7 +95,7 @@
},
{
"cell_type": "code",
"execution_count": 90,
"execution_count": 197,
"metadata": {},
"outputs": [],
"source": [
@ -108,7 +105,7 @@
},
{
"cell_type": "code",
"execution_count": 91,
"execution_count": 198,
"metadata": {},
"outputs": [],
"source": [
@ -117,7 +114,7 @@
},
{
"cell_type": "code",
"execution_count": 92,
"execution_count": 199,
"metadata": {},
"outputs": [],
"source": [
@ -129,28 +126,16 @@
},
{
"cell_type": "code",
"execution_count": 100,
"execution_count": 200,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
"<PIL.Image.Image image mode=RGB size=648x124>"
]
},
"execution_count": 100,
"metadata": {},
"output_type": "execute_result"
}
],
"outputs": [],
"source": [
"# PILversions[9]"
"# PILversions[12]"
]
},
{
"cell_type": "code",
"execution_count": 94,
"execution_count": 201,
"metadata": {},
"outputs": [],
"source": [
@ -160,7 +145,7 @@
},
{
"cell_type": "code",
"execution_count": 95,
"execution_count": 202,
"metadata": {},
"outputs": [],
"source": [
@ -172,7 +157,7 @@
},
{
"cell_type": "code",
"execution_count": 96,
"execution_count": 203,
"metadata": {},
"outputs": [],
"source": [
@ -185,7 +170,7 @@
},
{
"cell_type": "code",
"execution_count": 97,
"execution_count": 204,
"metadata": {},
"outputs": [],
"source": [
@ -194,7 +179,7 @@
},
{
"cell_type": "code",
"execution_count": 98,
"execution_count": 205,
"metadata": {},
"outputs": [],
"source": [
@ -209,24 +194,53 @@
},
{
"cell_type": "code",
"execution_count": 99,
"execution_count": 206,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"WALKER'S\n",
"CHOCOLATES\n",
"NO RETURNS OR EXCHANGES\n",
"ON FOOD ITEMS.\n",
"REG 09-22-2023 12:08\n",
"000021\n",
"1 BAKING NT $14.40\n",
"TL $14.40\n",
"CREDIT : $14.40\n",
"LIFE S SHORT\n",
"EAT CHOCOLATE\n",
"Canada Computers\n",
"920 Upper Wentworth Street, Unit 1\n",
"Hamilton, ON LSA 5C5\n",
"905-388-5900\n",
"HST# : 882966712RT0081\n",
"==============\n",
"Invoice No : ARHM00352964\n",
"09/09/2023 1:43:12 PM\n",
"Cashier : Francesco\n",
"1 NTTP100137 24.99\n",
"TP- LINK ( Archer T3U PLUS ) ACI\n",
"300 High Gain Wireless\n",
"PART# : Archer T3U PLUS\n",
"[ Warranty : Defective Exchange\n",
":30 Days ; Manufacturing Warrant\n",
"y : 2 Years : ]\n",
"2233038004384\n",
"Subtotal : $24.99\n",
"HST : $3.25\n",
"Total : $28.24\n",
"TRANSACTION REGORD\n",
"TYPE : PURCHASE\n",
"ACCT : VISA $ 28.24\n",
"CARD NUMBER : *********** #845\n",
"DATE/TIME : 23/09/09 13:43:11\n",
"REFERENCE #: [6656723010010012980\n",
"AUTHORIZATION #: 093481\n",
"VISA CREDIT\n",
"A0000000031010\n",
"8080008000 6800\n",
"01/027 Approved - Thank You\n",
"IMPORTANT\n",
"Retain this copy for your records\n",
"*** CARDHOLDER COPY ***\n",
"Returns and exchanges : Please visit\n",
"http://www. canadacomputers. com/re\n",
"turns-exchanges for full return and\n",
"exchange details.\n",
"0' 0\n",
"-\n",
"\n"
]
}