简体   繁体   中英

How to remove background gray drawings from image in OPENCV python

I need to remove the gray drawing from the image background and only need symbols drawn over it.

Here is my code to do that using morphologyEx but it did not remove the entire gray drawing that is in background.

img_path = "images/new_drawing.png"
img = cv2.imread(img_path)

kernel = np.ones((2,2), dtype=np.uint8)
result = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=1)
cv2.imshow('Without background',result);

cv2.waitKey(0)
cv2.destroyAllWindows()

I tried this also and got expected results in grayscale but unable to convert it to BGR.

Here is my code

img = cv2.imread('images/new_drawing.png')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
med_blur = cv2.medianBlur(gray_img, ksize=3)

_, thresh = cv2.threshold(med_blur, 190, 255, cv2.THRESH_BINARY)
blending = cv2.addWeighted(gray_img, 0.5, thresh, 0.9, gamma=0)
cv2.imshow("blending", blending);

Also i used contours to identify symbols and draw them to white image but problem is that it also identify background drawing that i don't want.

Input image

在此处输入图像描述

Expected output image

在此处输入图像描述

Also the drawing will be always in gray color as in image.

Please help me out to get better result.

Here is one way to do that in Python/OpenCV.

  • Read the input
  • Convert to HSV and separate channels
  • Threshold the saturation channel
  • Threshold the value channel and invert
  • Combine the two threshold images as a mask
  • Apply the mask to the input to write white where the mask is black
  • Save the result

Input:

在此处输入图像描述

import cv2
import numpy as np

# read image
img = cv2.imread('symbols.png')

# convert image to hsv colorspace
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)

# threshold saturation image
thresh1 = cv2.threshold(s, 92, 255, cv2.THRESH_BINARY)[1]

# threshold value image and invert
thresh2 = cv2.threshold(v, 128, 255, cv2.THRESH_BINARY)[1]
thresh2 = 255 - thresh2

# combine the two threshold images as a mask
mask = cv2.add(thresh1,thresh2)

# use mask to remove lines in background of input
result = img.copy()
result[mask==0] = (255,255,255)

# display IN and OUT images
cv2.imshow('IMAGE', img)
cv2.imshow('SAT', s)
cv2.imshow('VAL', v)
cv2.imshow('THRESH1', thresh1)
cv2.imshow('THRESH2', thresh2)
cv2.imshow('MASK', mask)
cv2.imshow('RESULT', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

# save output image
cv2.imwrite('symbols_thresh1.png', thresh1)
cv2.imwrite('symbols_thresh2.png', thresh2)
cv2.imwrite('symbols_mask.png', mask)
cv2.imwrite('symbols_cleaned.png', result)


Saturation channel thresholded:

在此处输入图像描述

Value channel thresholded and inverted:

在此处输入图像描述

Mask:

在此处输入图像描述

Result:

在此处输入图像描述

You are almost there...

Instead of using cv2.inRange to "catch" the non-gray pixel I suggest using cv2.inRange for catching all the pixels you want to change to white color:

mask = cv2.inRange(hsv, (0, 0, 100), (255, 5, 255))
  • The hue range is irrelevant.
  • The saturation is close to zero (shades of gray).
  • The brightness excludes the black pixels (you like to keep).

In order to get a nicer solution, I also used the following additional stages:

  • Build a mask of non-black pixels:

     nzmask = cv2.inRange(hsv, (0, 0, 5), (255, 255, 255))
  • Erode the above mask:

     nzmask = cv2.erode(nzmask, np.ones((3,3)))
  • Apply and operation between mask and nzmask :

     mask = mask & nzmask

The above stages keeps the gray pixels around the black text.
Without the above stages, the black text gets thinner.

  • The last stage is replacing mask pixels with white:

     new_img = img.copy() new_img[np.where(mask)] = 255

Here is the code:

import numpy as np
import cv2

img_path = "new_drawing.png"
img = cv2.imread(img_path)

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

mask = cv2.inRange(hsv, (0, 0, 100), (255, 5, 255))
cv2.imshow('mask before and with nzmask', mask);

# Build mask of non black pixels.
nzmask = cv2.inRange(hsv, (0, 0, 5), (255, 255, 255))

# Erode the mask - all pixels around a black pixels should not be masked.
nzmask = cv2.erode(nzmask, np.ones((3,3)))
cv2.imshow('nzmask', nzmask);

mask = mask & nzmask

new_img = img.copy()
new_img[np.where(mask)] = 255

cv2.imshow('mask', mask);
cv2.imshow('new_img', new_img);
cv2.waitKey(0)
cv2.destroyAllWindows()

Result:
在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM