Fixing whiteout background again.

Changed the technique to find the edges because it proved inconsistent.

Signed-off-by: Ethan Wellenreiter <ewellenreiter@gmail.com>
This commit is contained in:
Ethan Wellenreiter 2023-11-14 21:48:39 -05:00
parent 70cabaabd4
commit edeb73cca3
2 changed files with 194 additions and 88 deletions

View File

@ -2,7 +2,7 @@
"cells": [
{
"cell_type": "code",
"execution_count": 2312,
"execution_count": 143,
"metadata": {},
"outputs": [],
"source": [
@ -15,17 +15,78 @@
},
{
"cell_type": "code",
"execution_count": 2313,
"execution_count": 144,
"metadata": {},
"outputs": [],
"source": [
"# img = cv2.imread('/mnt/dataset/baseimages/1.jpg')\n",
"img = cv2.imread('/mnt/code/autocropper/test_images/IMG_7594.jpg')"
"import os\n",
"import pathlib\n",
"\n",
"def testondataset(pathtodataset, function):\n",
" imagefileextensions = [\".jpg\", \".png\"]\n",
" filenames = next(os.walk(pathtodataset), (None, None, []))[2]\n",
" \n",
" outs = []\n",
" for filename in filenames:\n",
" suffix = pathlib.Path(filename).suffix\n",
" if (suffix not in imagefileextensions):\n",
" print(\"Not a valid image \"+filename)\n",
" continue\n",
" img = cv2.imread(pathtodataset+filename)\n",
" outs.append(function(img))\n",
" return outs\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 2314,
"execution_count": 145,
"metadata": {},
"outputs": [],
"source": [
"def showimgs(imgs):\n",
" if (isinstance(imgs, np.ndarray)):\n",
" if (imgs.shape[0] > imgs.shape[1]):\n",
" cv2.imshow(\"test\", mf.ResizeWithAspectRatio(imgs, height=1350))\n",
" else:\n",
" cv2.imshow(\"test\", mf.ResizeWithAspectRatio(imgs, width=1000))\n",
" else:\n",
" for i, out in enumerate(imgs):\n",
" if (out.shape[0] > out.shape[1]):\n",
" cv2.imshow(\"test\"+str(i), mf.ResizeWithAspectRatio(out, height=1350))\n",
" else:\n",
" cv2.imshow(\"test\"+str(i), mf.ResizeWithAspectRatio(out, width=1000))\n",
" cv2.waitKey(0)\n",
" cv2.destroyAllWindows()"
]
},
{
"cell_type": "code",
"execution_count": 146,
"metadata": {},
"outputs": [],
"source": [
"def writeimgs(directorypath, imgs):\n",
" if (isinstance(imgs, np.ndarray)):\n",
" cv2.imwrite(directorypath+\"test.jpg\", imgs)\n",
" else:\n",
" for i, out in enumerate(imgs):\n",
" cv2.imwrite(directorypath+\"test\"+str(i)+\".jpg\", out)"
]
},
{
"cell_type": "code",
"execution_count": 147,
"metadata": {},
"outputs": [],
"source": [
"img = cv2.imread('/mnt/dataset/baseimages/3.jpg')\n",
"# img = cv2.imread('/mnt/code/autocropper/test_images/IMG_7594.jpg')"
]
},
{
"cell_type": "code",
"execution_count": 148,
"metadata": {},
"outputs": [],
"source": [
@ -36,35 +97,49 @@
" # blur = cv2.blur(gray, (7,7))\n",
" \n",
" # window = 51\n",
" window = min(gray.shape[1], gray.shape[0])//20\n",
" window = gray.shape[1]//8\n",
" if window % 2 == 0:\n",
" window += 1\n",
" thresh1 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, window, 5)\n",
" thresh2 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)[1]\n",
" thresh = cv2.bitwise_and(thresh1, thresh2)\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",
" # dim = int(min(thresh.shape[0], thresh.shape[1])/400)\n",
" dim = 3\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" morphedthresh = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel)\n",
" # dim = 3\n",
" # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" # morphedthresh = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel)\n",
" # return morphedthresh\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",
" 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",
" biggestcontour1 = max(contours1, key=cv2.contourArea)\n",
" # biggestcontour2 = 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.001*cv2.arcLength(approx,True)\n",
" approx = cv2.approxPolyDP(approx,epsilon,True)\n",
" # approx = cv2.convexHull(biggestcontour1)\n",
" # print(approx)\n",
" \n",
" # biggestcontour1 = max(contours1, key=cv2.contourArea)\n",
" biggestcontour2 = max(contours2, key=cv2.contourArea)\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, (0,255,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, [biggestcontour2], -1, (0,0,0), thickness=cv2.FILLED)\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",
@ -79,10 +154,33 @@
" mask = 255 - cv2.morphologyEx(invertmask, cv2.MORPH_ERODE, kernel, iterations=1)\n",
" # return mask\n",
" \n",
" mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)\n",
" whitedbackground = cv2.bitwise_or(image, mask)\n",
" mask1 = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)\n",
" whitedbackground = cv2.bitwise_or(image, mask1)\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=3)\n",
" # return morphedmask\n",
" \n",
" finalmask = cv2.bitwise_or(mask, 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",
" \n",
" \n",
" \n",
" \n",
" gray2 = cv2.cvtColor(whitedbackground, cv2.COLOR_BGR2GRAY)\n",
"\n",
" canny = cv2.Canny(gray2, 0, 500, None, 3)\n",
@ -96,7 +194,7 @@
" # print(dim)\n",
" dim = int(min(maskgray.shape[0], maskgray.shape[1])/200)\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" morphedmask = cv2.morphologyEx(invert, cv2.MORPH_ERODE, kernel)\n",
" morphedmask = cv2.morphologyEx(invert, cv2.MORPH_ERODE, kernel, iterations=2)\n",
" dim = int(min(maskgray.shape[0], maskgray.shape[1])/50)\n",
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))\n",
" morphedmask = cv2.morphologyEx(morphedmask, cv2.MORPH_OPEN, kernel, iterations=7)\n",
@ -119,7 +217,7 @@
},
{
"cell_type": "code",
"execution_count": 2315,
"execution_count": 149,
"metadata": {},
"outputs": [],
"source": [
@ -139,12 +237,14 @@
},
{
"cell_type": "code",
"execution_count": 2316,
"execution_count": 150,
"metadata": {},
"outputs": [],
"source": [
"def houghlineprocessing(image):\n",
" croppedanddeskewed, _ = mf.houghlinedeskewandcrop(image)\n",
" return croppedanddeskewed\n",
" \n",
" \n",
" postprocessed = cropclarifying(croppedanddeskewed)\n",
" # return postprocessed\n",
@ -168,12 +268,12 @@
},
{
"cell_type": "code",
"execution_count": 2317,
"execution_count": 151,
"metadata": {},
"outputs": [],
"source": [
"# prepped, scaler, hp, vp = mf.squareandthenresize(img, fill=255, width=1000, returnscalerinfo=True)\n",
"outs = mf.houghlineprocessing(img)\n",
"outs = houghlineprocessing(img)\n",
"# outs = houghlinedeskewandcrop(img)\n",
"# outs = outs[0]\n",
"# print(croprect)\n",
@ -182,7 +282,7 @@
},
{
"cell_type": "code",
"execution_count": 2318,
"execution_count": 152,
"metadata": {},
"outputs": [],
"source": [
@ -196,7 +296,7 @@
},
{
"cell_type": "code",
"execution_count": 2319,
"execution_count": 153,
"metadata": {},
"outputs": [],
"source": [
@ -208,38 +308,16 @@
},
{
"cell_type": "code",
"execution_count": 2320,
"execution_count": 154,
"metadata": {},
"outputs": [],
"source": [
"def showimgs(imgs):\n",
" if (isinstance(imgs, np.ndarray)):\n",
" if (imgs.shape[0] > imgs.shape[1]):\n",
" cv2.imshow(\"test\", mf.ResizeWithAspectRatio(imgs, height=1350))\n",
" else:\n",
" cv2.imshow(\"test\", mf.ResizeWithAspectRatio(imgs, width=1000))\n",
" else:\n",
" for i, out in enumerate(imgs):\n",
" if (out.shape[0] > out.shape[1]):\n",
" cv2.imshow(\"test\"+str(i), mf.ResizeWithAspectRatio(out, height=1350))\n",
" else:\n",
" cv2.imshow(\"test\"+str(i), mf.ResizeWithAspectRatio(out, width=1000))\n",
" cv2.waitKey(0)\n",
" cv2.destroyAllWindows()"
"# showimgs(outs)"
]
},
{
"cell_type": "code",
"execution_count": 2321,
"metadata": {},
"outputs": [],
"source": [
"showimgs(outs)"
]
},
{
"cell_type": "code",
"execution_count": 2322,
"execution_count": 155,
"metadata": {},
"outputs": [],
"source": [
@ -266,6 +344,33 @@
"# cv2.waitKey(0)\n",
"# cv2.destroyAllWindows()"
]
},
{
"cell_type": "code",
"execution_count": 156,
"metadata": {},
"outputs": [],
"source": [
"results = testondataset(\"/mnt/dataset/baseimages/\", houghlineprocessing)"
]
},
{
"cell_type": "code",
"execution_count": 157,
"metadata": {},
"outputs": [],
"source": [
"# showimgs(results)"
]
},
{
"cell_type": "code",
"execution_count": 158,
"metadata": {},
"outputs": [],
"source": [
"writeimgs(\"/mnt/code/autocropper/result_images/\", results)"
]
}
],
"metadata": {

View File

@ -504,35 +504,49 @@ def whiteoutbackground(image):
# blur = cv2.blur(gray, (7,7))
# window = 51
window = min(gray.shape[1], gray.shape[0])//20
window = gray.shape[1]//8
if window % 2 == 0:
window += 1
thresh1 = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, window, 5)
thresh2 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)[1]
thresh = cv2.bitwise_and(thresh1, thresh2)
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, window, 2)
# thresh2 = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)[1]
# thresh = cv2.bitwise_and(thresh1, thresh2)
# return thresh
# dim = int(min(thresh.shape[0], thresh.shape[1])/400)
dim = 3
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))
morphedthresh = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel)
# dim = 3
# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))
# morphedthresh = cv2.morphologyEx(thresh, cv2.MORPH_ERODE, kernel)
# return morphedthresh
# contours1, heirarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours2, heirarchy = cv2.findContours(morphedthresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours1, heirarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# contours2, heirarchy = cv2.findContours(morphedthresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
biggestcontour1 = max(contours1, key=cv2.contourArea)
# biggestcontour2 = max(contours2, key=cv2.contourArea)
epsilon = 0.0005*cv2.arcLength(biggestcontour1,True)
approx = cv2.approxPolyDP(biggestcontour1,epsilon,True)
# approx = cv2.convexHull(approx)
epsilon = 0.001*cv2.arcLength(approx,True)
approx = cv2.approxPolyDP(approx,epsilon,True)
# approx = cv2.convexHull(biggestcontour1)
# print(approx)
# biggestcontour1 = max(contours1, key=cv2.contourArea)
biggestcontour2 = max(contours2, key=cv2.contourArea)
# imagecpy = cv2.drawContours(imagecpy, [biggestcontour1], -1, (0,255,0), thickness=3)
# imagecpy = cv2.drawContours(imagecpy, [biggestcontour2], -1, (0,0,255), thickness=3)
# imagecpy = cv2.drawContours(imagecpy, [approx], -1, (0,255,0), thickness=3)
# return imagecpy
blank = np.full(thresh.shape, 255, dtype=np.uint8)
mask = blank.copy()
# mask = cv2.drawContours(mask, [biggestcontour1], -1, (0,0,0), thickness=cv2.FILLED)
mask = cv2.drawContours(mask, [biggestcontour2], -1, (0,0,0), thickness=cv2.FILLED)
mask = cv2.drawContours(mask, [biggestcontour1], -1, (0,0,0), thickness=cv2.FILLED)
# mask = cv2.drawContours(mask, [approx], -1, (0,0,0), thickness=cv2.FILLED)
# mask = cv2.drawContours(mask, [biggestcontour2], -1, (0,0,0), thickness=cv2.FILLED)
# return mask
@ -547,34 +561,21 @@ def whiteoutbackground(image):
mask = 255 - cv2.morphologyEx(invertmask, cv2.MORPH_ERODE, kernel, iterations=1)
# return mask
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
whitedbackground = cv2.bitwise_or(image, mask)
mask1 = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
whitedbackground = cv2.bitwise_or(image, mask1)
# return whitedbackground
gray2 = cv2.cvtColor(whitedbackground, cv2.COLOR_BGR2GRAY)
canny = cv2.Canny(gray2, 0, 500, None, 3)
mask2 = blank.copy()
mask2 = 255-cv2.drawContours(mask2, [approx], -1, (0,0,0), thickness=cv2.FILLED)
maskgray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
invert = 255-maskgray
# dim = 21
# print(dim)
dim = int(min(maskgray.shape[0], maskgray.shape[1])/200)
dim = int(min(mask2.shape[0], mask2.shape[1])/50)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))
morphedmask = cv2.morphologyEx(invert, cv2.MORPH_ERODE, kernel)
dim = int(min(maskgray.shape[0], maskgray.shape[1])/50)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (dim, dim))
morphedmask = cv2.morphologyEx(morphedmask, cv2.MORPH_OPEN, kernel, iterations=7)
# return 255 - morphedmask
morphedmask = 255 - morphedmask
finalmask = cv2.bitwise_or(morphedmask, maskgray)
# return finalmask
morphedmask = 255-cv2.morphologyEx(mask2, cv2.MORPH_OPEN, kernel, iterations=3)
# return morphedmask
finalmask = cv2.bitwise_or(mask, morphedmask)
# edgecontours, _ = cv2.findContours(255-morphedmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
finalmaskbgr = cv2.cvtColor(finalmask, cv2.COLOR_GRAY2BGR)
# return finalmaskbgr