Unable to crop white background off a flatbed scan

Question:

I have scanned images of various products packagings as following
enter image description here

These are in different sizes. I need to remove white background on right and under. I have tried several solutions but only following code is giving me the best results.

import cv2
import numpy as np

# Load image, convert to grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread("img.jpg")
original = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Obtain bounding rectangle and extract ROI
x,y,w,h = cv2.boundingRect(thresh)
cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 2)
ROI = original[y:y+h, x:x+w]

# Add alpha channel
b,g,r = cv2.split(ROI)
alpha = np.ones(b.shape, dtype=b.dtype) * 50
ROI = cv2.merge([b,g,r,alpha])

cv2.imwrite('thresh.jpg', thresh)
cv2.imwrite('image.jpg', image)
cv2.imwrite('ROI.jpg', ROI)

But still it is not cropping out whole white background as it can be seen in following image it only selects a part of it and then crops it. Please can some help me with how can I properly remove white background? Thank you.
enter image description here

Asked By: Raza Ul Haq

||

Answers:

I didn’t use the "opencv" library, I have used "skimage".
After removing the white background, the resolution of the picture has been affected, I don’t know if you can accept it. Here is the code:

from skimage import io
def corp_margin(img, threshold=600):
        img2=img.sum(axis=2)
        (row,col)=img2.shape
        row_top=0
        raw_down=0
        col_top=0
        col_down=0
        for r in range(0,row):
                if img2.sum(axis=1)[r]<threshold*col:
                        row_top=r
                        break
 
        for r in range(row-1,0,-1):
                if img2.sum(axis=1)[r]<threshold*col:
                        raw_down=r
                        break
 
        for c in range(0,col):
                if img2.sum(axis=0)[c]<threshold*row:
                        col_top=c
                        break
 
        for c in range(col-1,0,-1):
                if img2.sum(axis=0)[c]<threshold*row:
                        col_down=c
                        break
 
        new_img=img[row_top:raw_down+1,col_top:col_down+1,0:3]
        return new_img
image = io.imread("img.jpg")
img_re = corp_margin(image)
io.imshow(img_re)
io.imsave('new_image.jpg', img_re)

Here is the result I got :
enter image description here

Answered By: HMH1013
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.