How do you identify if the image is cut at the edges using OpenCV?

asked 2020-08-07 12:06:30 -0500

updated 2020-08-07 12:22:17 -0500

supra56 gravatar image

C:\fakepath\8213227~_memo.jpg

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')
edit retag flag offensive close merge delete

Comments

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

mvuori gravatar imagemvuori ( 2020-08-07 12:24:02 -0500 )edit

If the image is an original or not.

supra56 gravatar imagesupra56 ( 2020-08-07 12:31:57 -0500 )edit

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.

despair104 gravatar imagedespair104 ( 2020-08-08 12:45:10 -0500 )edit