How do you identify if the image is cut at the edges using OpenCV?
Using OpenCV I would like to identify the above image is incomplete due to the right hand side edges are cut. Below is the code I tried but no success.
import cv2
import numpy as np
# Load image, create mask, grayscale, and Otsu's threshold`
image = cv2.imread('test.jpg')
image1 = cv2.imread('test.jpg')
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,11,3)
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (40,1))
detect_horizontal = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(mask, [c], -1, (255,255,255), -1)
# Find vertical sections and draw on mask
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,80))
detect_vertical = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
cv2.drawContours(mask, [c], -1, (0,0,255), -1)
# Fill text document body
mask = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)
close_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, close_kernel, iterations=3)
_,cnts,hierarchy = cv2.findContours(close, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
hierarchy = hierarchy[0]
for i,c in enumerate(cnts):
cv2.drawContours(mask, [c], -1, 255, -1)
#print('cnt num',i)
#print('cnt num',cnts[i])
print('heir',hierarchy[i])
if hierarchy[i][2] < 0 and hierarchy[i][3] < 0:
cv2.drawContours(image, cnts, i, (0,0,255), 3)
else:
cv2.drawContours(image, cnts, i, (0,255,0), 3)
opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, close_kernel, iterations=5)
_,cnts,hierarchy = cv2.findContours(opening, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
hierarchy = hierarchy[0]
for i,c in enumerate(cnts):
cv2.drawContours(mask, [c], -1, 255, -1)
if hierarchy[i][2] < 0 and hierarchy[i][3] < 0:
cv2.drawContours(image1, cnts, i, (0,0,255), 3)
else:
cv2.drawContours(image1, cnts, i, (0,255,0), 3)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
displayCnt = None
print('contour:',cnts)
for c in cnts:
# Perform contour approximation
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.02 * peri, True)
if len(approx) == 4:
displayCnt = approx
break
if displayCnt is None:
print('The image is incomplete')
I don't understand what the code tries to do - which is the first thing to describe and for others to understand..
The way I think, one would search for either1) contours that are clipped by right edge and extend somewhat to left, ot 2) narrow vertical contour reptesenting the background below the paper - not in this paricular image
If the image is an original or not.
I also have a hard time understanding what the code is meant to do.
So you want to detect if the edges are cut. The image itself is full of edges, try giving a read at the opencv edges tutorials and you'll see how the computer defines an edge.
Since there are edges everywhere, we don't know what you mean by cut since opencv does not know what the full image looks like.
I think you want to see if the little black square/rectangle at the top right corner is complete or not. You could take a full image, draw the outer contours (only of the area you are interested in) and then match them to the contours of this image using cv.matchShapes(). After some runs of this, you could define a threshhold to determine if it is complete or not based on the match score.