Checkpoint in making the rotation not have black fill spots

For autocropping/deskewing, need the rotation to not have
the black fill spots since they tend to mess up the later
background whiteing-out.

Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
This commit is contained in:
Ethan Wellenreiter 2023-11-23 17:52:01 -05:00
parent c2ca87eea5
commit 6465a49cfe
2 changed files with 165 additions and 78 deletions

View File

@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 3033,
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
@ -15,7 +15,7 @@
},
{
"cell_type": "code",
"execution_count": 3034,
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
@ -55,7 +55,7 @@
},
{
"cell_type": "code",
"execution_count": 3035,
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
@ -77,7 +77,7 @@
},
{
"cell_type": "code",
"execution_count": 3036,
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
@ -91,25 +91,28 @@
},
{
"cell_type": "code",
"execution_count": 3037,
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"img = cv2.imread('/mnt/dataset/baseimages/12.jpg')\n",
"img = cv2.imread('/mnt/dataset/baseimages/15.jpg')\n",
"# img = cv2.imread('/mnt/code/autocropper/test_images/IMG_7605.jpg')\n",
"testall = False"
]
},
{
"cell_type": "code",
"execution_count": 3038,
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"## NEED TO FIX THE EARLIER PARTS SO THAT IT DOESN'T HAVE THOSE BLACK SECTIONS AFTER THE ROTATION\n",
"\n",
"\n",
"def whiteoutbackground(image):\n",
" sdim = int(min(image.shape[0], image.shape[1])/10)\n",
" skernel = cv2.getStructuringElement(cv2.MORPH_RECT, (sdim, sdim))\n",
" srkernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (sdim, sdim))\n",
" srkernel = cv2.getStructuringElement(cv2.MORPH_RECT, (sdim, sdim))\n",
" skernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (sdim, sdim))\n",
" \n",
" \n",
" lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)\n",
@ -129,7 +132,7 @@
" blurimage1 = cv2.blur(laba, (5,5))\n",
" blurimage2 = cv2.blur(labb, (5,5))\n",
" \n",
" window = lab.shape[1]//5\n",
" window = lab.shape[1]//3\n",
" if window % 2 == 0:\n",
" window += 1\n",
" thresh1 = cv2.adaptiveThreshold(blurimage1, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 0)\n",
@ -137,10 +140,12 @@
" if window % 2 == 0:\n",
" window += 1\n",
" thresh2 = cv2.adaptiveThreshold(blurimage2, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 0)\n",
" # return thresh1\n",
" imglist.append(thresh1)\n",
" imglist.append(thresh2)\n",
" threshmerge = cv2.bitwise_or(thresh1, thresh2)\n",
" imglist.append(threshmerge)\n",
" # return threshmerge\n",
" \n",
" dim = int(min(threshmerge.shape[0], threshmerge.shape[1])/100)\n",
" # dim = 2\n",
@ -151,6 +156,7 @@
" 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",
@ -162,13 +168,15 @@
" # 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, srkernel, iterations=2)\n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=2)\n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=2)\n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, srkernel)\n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, skernel)\n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=2)\n",
" mask1 = mask1[sdim:-sdim, sdim:-sdim]\n",
" imglist.append(mask1)\n",
" # return mask1\n",
" \n",
" maskc = cv2.cvtColor(mask1, cv2.COLOR_GRAY2BGR)\n",
" whitedbackground = cv2.bitwise_or(image, maskc)\n",
@ -180,38 +188,6 @@
" \n",
" \n",
" \n",
" # contours, heirarchy = cv2.findContours(255-threshmerge, 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 = cv2.drawContours(mask1, [biggestcontour], -1, 0, thickness=cv2.FILLED)\n",
" # # temp = cv2.drawContours(image, [biggestcontour], -1, 255, thickness=3)\n",
" # # imglist.append(temp)\n",
" \n",
" # mask1 = mf.padWithColour(mask1, sdim, sdim, fill=255)\n",
" \n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel, iterations=1)\n",
" # mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, skernel)\n",
" # mask1 = mask1[sdim:-sdim, sdim:-sdim]\n",
" # imglist.append(mask1)\n",
" \n",
" # mask1merge = cv2.bitwise_and(mask1, mask1t)\n",
" # imglist.append(mask1merge)\n",
" \n",
" \n",
" \n",
" # maskc = cv2.cvtColor(mask1merge, cv2.COLOR_GRAY2BGR)\n",
" # # return maskc\n",
" # # return blurimage\n",
" # # print(blurimage)\n",
" # # print(maskc)\n",
" # whitedbackground = cv2.bitwise_or(image, maskc)\n",
" # imglist.append(whitedbackground)\n",
"\n",
" # return imglist\n",
" \n",
" \n",
" imagecpy = image.copy()\n",
" blurimage = cv2.blur(imagecpy, (13,13))\n",
" \n",
@ -227,15 +203,18 @@
" # imagecpy = cv2.copyMakeBorder(blurimage, sdim, sdim, sdim, sdim, cv2.BORDER_REPLICATE)\n",
" # return imagecpy\n",
" # imagecpy = mf.padWithColour(image, hpadding=sdim, vpadding=sdim)\n",
" gray = cv2.cvtColor(blurimage, cv2.COLOR_BGR2GRAY)\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]//15\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, 5)\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",
@ -257,7 +236,7 @@
" # dim = dotsize\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" morphedthresh = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel)\n",
" # return morphedthresh\n",
" return morphedthresh\n",
" \n",
" \n",
" contours, heirarchy = cv2.findContours(morphedthresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
@ -273,8 +252,8 @@
" \n",
" mask1 = mf.padWithColour(mask1, sdim, sdim, fill=0)\n",
" \n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_CLOSE, skernel)\n",
" mask1 = cv2.morphologyEx(mask1, cv2.MORPH_OPEN, skernel)\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",
@ -469,7 +448,7 @@
},
{
"cell_type": "code",
"execution_count": 3039,
"execution_count": 28,
"metadata": {},
"outputs": [],
"source": [
@ -489,13 +468,100 @@
},
{
"cell_type": "code",
"execution_count": 3040,
"execution_count": 29,
"metadata": {},
"outputs": [],
"source": [
"def houghlinedeskewthencrop(baseimage, preppedimage, rotationangle, croprect):\n",
" # rotateddst1 = rotatewithexactpadding(preppedimage, rotationangle, fill=0)\n",
" # rotatedbaseimage = rotatewithexactpadding(baseimage, rotationangle, fill=(0,0,0))\n",
" # print(croprect)\n",
" hpad, vpad = mf.determineextrapadding(croprect[3], croprect[2], rotationangle)\n",
" # print(rotationangle)\n",
" # print(hpad, vpad)\n",
" adjustedrect = [croprect[0]-hpad, croprect[1]-vpad, croprect[2]+(2*hpad), croprect[3]+(2*vpad)]\n",
" adjustedrect = [int(s) for s in adjustedrect]\n",
" leftpad = -min(0, adjustedrect[0])\n",
" toppad = -min(0, adjustedrect[1])\n",
" rightpad = -min(0, baseimage.shape[1]-(adjustedrect[0]+adjustedrect[2]))\n",
" bottompad = -min(0, baseimage.shape[0]-(adjustedrect[1]+adjustedrect[3]))\n",
" \n",
" adjustedrect = [max(0, s) for s in adjustedrect]\n",
" \n",
" # print(leftpad, rightpad, toppad, bottompad)\n",
" ## DETERMINE PADDING AMOUNTS BECAUSE I THEN NEED TO PAD THE ORIGINAL IMAGE, CROP IT TO THE FIRST LEVEL, ROTATE, AND THEN CROP AGAIN\n",
" # print(adjustedrect)\n",
" # adjustedrect = croprect\n",
" borderType = cv2.BORDER_CONSTANT\n",
" padded = cv2.copyMakeBorder(baseimage, toppad, bottompad, leftpad, rightpad, borderType)\n",
" croppedpaddedimage = padded[adjustedrect[1]:adjustedrect[1]+adjustedrect[3], adjustedrect[0]:adjustedrect[0]+adjustedrect[2], :]\n",
" # print(croprect[2], croprect[3])\n",
" # print(croppedpaddedimage.shape)\n",
" # croppedog = baseimage[croprect[1]:croprect[1]+croprect[3], croprect[0]:croprect[0]+croprect[2], :]\n",
" # return croppedpaddedimage, croppedog\n",
" \n",
" rotatedbaseimage = mf.rotate(croppedpaddedimage, rotationangle)\n",
" \n",
" # print(vpad, hpad)\n",
" # print(croprect)\n",
" rotatedbaseimage = rotatedbaseimage[vpad:vpad+croprect[1]+croprect[3], hpad:hpad+croprect[0]+croprect[2], :]\n",
" # return rotatedbaseimage, 5\n",
" \n",
" \n",
" # print(preppedimage.shape)\n",
" rotateddst1 = mf.rotate(preppedimage, rotationangle)\n",
" # print(rotateddst1.shape)\n",
" # print(rotatedbaseimage.shape)\n",
" # return rotatedbaseimage, 5\n",
"\n",
" \n",
" sizemultiplier = rotatedbaseimage.shape[0]/rotateddst1.shape[0]\n",
" # print(sizemultiplier)\n",
" # return rotatedbaseimage, rotationangle\n",
"\n",
" croppedbaseimage = mf.houghlinepcrop(rotatedbaseimage, rotateddst1, sizemultiplier)\n",
"\n",
" finalbaseimage = mf.contourcrop(croppedbaseimage)\n",
"\n",
"\n",
" return finalbaseimage, rotationangle"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [],
"source": [
"def houghlinedeskewandcrop(image):\n",
" canny, ogimage, rect = mf.prepimageforhoughline(image, returnrect=True) ## scaling and cropping occurs. need to also return the changes done\n",
" # return canny, croppedogimage\n",
" # print(canny.shape)\n",
" # print(croppedogimage.shape)\n",
"\n",
" ## -----------------finding angle to deskew-----------------\n",
" rotationangle = mf.houghlinedeskewangle(canny)\n",
" # print(rotationangle)\n",
"\n",
" \n",
" # rotatorrect = findcroprectforangle(rect, angle)\n",
"\n",
" # -----------------end of finding angle to deskew-----------------\n",
"\n",
" ## -----------------deskewing and then cropping-----------------\n",
" outimg, angle = houghlinedeskewthencrop(ogimage, canny, rotationangle, rect)\n",
" return outimg, angle"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [],
"source": [
"def houghlineprocessing(image):\n",
" croppedanddeskewed, angle = mf.houghlinedeskewandcrop(image)\n",
" # return croppedanddeskewed\n",
" croppedanddeskewed, angle = houghlinedeskewandcrop(image)\n",
" return croppedanddeskewed\n",
" \n",
" \n",
" postprocessed = cropclarifying(croppedanddeskewed)\n",
@ -520,7 +586,16 @@
},
{
"cell_type": "code",
"execution_count": 3041,
"execution_count": 32,
"metadata": {},
"outputs": [],
"source": [
"# print(img.shape)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [],
"source": [
@ -535,7 +610,7 @@
},
{
"cell_type": "code",
"execution_count": 3042,
"execution_count": 34,
"metadata": {},
"outputs": [],
"source": [
@ -549,7 +624,7 @@
},
{
"cell_type": "code",
"execution_count": 3043,
"execution_count": 35,
"metadata": {},
"outputs": [],
"source": [
@ -561,7 +636,7 @@
},
{
"cell_type": "code",
"execution_count": 3044,
"execution_count": 36,
"metadata": {},
"outputs": [],
"source": [
@ -570,7 +645,7 @@
},
{
"cell_type": "code",
"execution_count": 3045,
"execution_count": 37,
"metadata": {},
"outputs": [],
"source": [
@ -580,7 +655,7 @@
},
{
"cell_type": "code",
"execution_count": 3046,
"execution_count": 38,
"metadata": {},
"outputs": [],
"source": [
@ -610,14 +685,14 @@
},
{
"cell_type": "code",
"execution_count": 3047,
"execution_count": 39,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"average time: 8.021544203162193(s)\n"
"average time: 0.1456429362297058(s)\n"
]
}
],
@ -628,7 +703,7 @@
},
{
"cell_type": "code",
"execution_count": 3048,
"execution_count": 40,
"metadata": {},
"outputs": [],
"source": [
@ -638,7 +713,7 @@
},
{
"cell_type": "code",
"execution_count": 3049,
"execution_count": 41,
"metadata": {},
"outputs": [],
"source": [
@ -647,7 +722,7 @@
},
{
"cell_type": "code",
"execution_count": 3050,
"execution_count": 42,
"metadata": {},
"outputs": [],
"source": [

View File

@ -91,10 +91,6 @@ def mergecontours(contours):
finalcontour = cv2.convexHull(cont)
return finalcontour
def padWithColour(img, hpadding=0, vpadding=0, fill=(0,0,0)):
borderType = cv2.BORDER_CONSTANT
out = cv2.copyMakeBorder(img, vpadding, vpadding, hpadding, hpadding, borderType, None, fill)
return out
# funtion to correct the median-angle to give it to the cv2.warpaffine() function
@ -346,7 +342,7 @@ def rotateLine(img, line, angle, returnint=True):
pt2 = rotatePoint(img, (line[2],line[3]), angle, returnint)
return (pt1[0], pt1[1], pt2[0], pt2[1])
def prepimageforhoughline(image):
def prepimageforhoughline(image, returnrect=True):
prepped, scaler, hp, vp = squareandthenresize(image, fill=255, width=1000, returnscalerinfo=True)
prepped, croprect = premorphCrop(prepped)
if (prepped.shape[1] > prepped.shape[0]):
@ -368,9 +364,12 @@ def prepimageforhoughline(image):
dst1 = cv2.Canny(dst1, 0, 500, None, 3)
# return dst1
accompaniedimage = image[finalcroprect[1]:finalcroprect[1]+finalcroprect[3], finalcroprect[0]:finalcroprect[0]+finalcroprect[2], :]
# accompaniedimage = squarepad(accompaniedimage, fill=255)
return dst1, accompaniedimage
if returnrect:
return dst1, image, finalcroprect
else:
accompaniedimage = image[finalcroprect[1]:finalcroprect[1]+finalcroprect[3], finalcroprect[0]:finalcroprect[0]+finalcroprect[2], :]
# accompaniedimage = squarepad(accompaniedimage, fill=255)
return dst1, accompaniedimage
def houghlinedeskewangle(image):
lines = cv2.HoughLines(image, 1, np.pi/180, int(max(image.shape[0], image.shape[1])/6), None, 0, 0)
@ -399,8 +398,7 @@ def houghlinedeskewangle(image):
rotationangle = np.rad2deg(mode)
return rotationangle
def determineextrapadding(img, angle):
h, w = img.shape[0], img.shape[1]
def determineextrapadding(h,w, angle):
radangle = abs(np.deg2rad(angle))
# print(radangle)
totalheightrot = w*np.sin(radangle) + h*np.cos(radangle)
@ -413,7 +411,8 @@ def determineextrapadding(img, angle):
return hpad, vpad
def rotatewithexactpadding(img, angle, fill=(0,0,0)):
hpad, vpad = determineextrapadding(img, angle)
h, w = img[0], img[1]
hpad, vpad = determineextrapadding(w,h, angle)
baseimage = padWithColour(img, hpad, vpad, fill=fill)
rotatedimg = rotate(baseimage, angle)
return rotatedimg
@ -477,8 +476,21 @@ def contourcrop(baseimage):
return finalbaseimage
def houghlinedeskewthencrop(baseimage, preppedimage, rotationangle):
rotateddst1 = rotatewithexactpadding(preppedimage, rotationangle, fill=0)
rotatedbaseimage = rotatewithexactpadding(baseimage, rotationangle, fill=(0,0,0))
# rotateddst1 = rotatewithexactpadding(preppedimage, rotationangle, fill=0)
# rotatedbaseimage = rotatewithexactpadding(baseimage, rotationangle, fill=(0,0,0))
hpad, vpad = mf.determineextrapadding(rect[3], rect[2], rotationangle)
adjustedrect = [rect[0]-hpad, rect[1]-vpad, rect[2]+(2*hpad), rect[3]+(2*vpad)]
croppedogimage = croppedogimage[adjustedrect[1]:adjustedrect[1]+adjustedrect[3], adjustedrect[0]:adjustedrect[0]+adjustedrect[2], :]
houghlinerotate()
print(preppedimage.shape)
rotateddst1 = rotate(preppedimage, rotationangle)
print(rotateddst1.shape)
rotatedbaseimage = rotate(baseimage, rotationangle)
sizemultiplier = rotatedbaseimage.shape[0]/rotateddst1.shape[0]
# print(sizemultiplier)
# return rotatedbaseimage, rotationangle