使用OpenCV自动去除背景色

2020-09-04 10:32:26 浏览数 (1)

几天前,我遇到了一个项目,要求将草图放到某个文件夹中时删除草图的白色背景。这都是在硬件扫描仪中发生的。

下面是一个草图示例:

第一步是安装此项目的依赖关系,具体需要内容我们将在下面列出。此外,我们还将使用Python 3.7。

代码语言:javascript复制
opencv_python==4.1.0.25
pip install opencv-python
numpy==1.16.4
pip install numpy

之后,我们将导入项目所需的所有模块

代码语言:javascript复制
import cv2
import os
import string
import random
from os import listdir
from os.path import isfile, join, splitext
import time
import sys
import numpy as np
import argparse

然后,我们创建三个不同的变量:要处理的文件夹的名称,图像在处理后存储的文件夹的名称,以及在监视文件夹时的轮询时间(即,它检查文件夹中更改的频率,在我们这里设置的是一秒钟)

代码语言:javascript复制
watch_folder = ‘toprocess’
processed_folder = ‘processed’
poll_time = 1

文件夹“ toprocess”和“ processed”放置在和我们的python脚本的同一目录中。

然后,我们将介绍我们程序主要功能的代码,它将监视我们的“ toprocess”目录,如果没有发生任何更改,程序将处理存入在该文件夹的所有图像。

代码语言:javascript复制
before = dict([(f, None) for f in os.listdir(watch_folder)])
while 1:
  time.sleep(poll_time)
  after = dict([(f, None) for f in os.listdir(watch_folder)])
  added = [f for f in after if not f in before]
  removed = [f for f in before if not f in after]
  if added:
    print(“Added “, “, “.join(added))
  if added[0] is not None:
    processImage(added[0])
  if removed:
    print(“Removed “, “, “.join(removed))
  before = after

这段代码将无限循环运行,直到脚本被杀死为止。启动后,它将文件存储在名为“ before”的词典目录中。接下来,下面将分解介绍无限循环中的步骤:

  • 睡眠指定的poll_time(1秒)。
  • 将文件信息存储在名为after的字典目录中。
  • 通过比较之后的IN和之前的NOT来存储已添加的内容
  • 检查最后添加的元素(added [0])(如果存在),然后调用一个函数,我们将在文件上稍作介绍的processImage进行讨论。
  • 如果已删除,请通过打印一些信息来让用户知道。
  • 最后,将目录中的最新文件进行更新。

接下来介绍processImage函数,这是程序的核心。这就是OpenCV后台删除魔术发生的地方。下面的注释解释了该代码(需要基本的OpenCV知识):

代码语言:javascript复制
def processImage(fileName):
  # Load in the image using the typical imread function using our watch_folder path, and the fileName passed in, then set the final output image to our current image for now
  image = cv2.imread(watch_folder   ‘/’   fileName)
  output = image
  # Set thresholds. Here, we are using the Hue, Saturation, Value color space model. We will be using these values to decide what values to show in the ranges using a minimum and maximum value. 
THESE VALUES CAN BE PLAYED AROUND FOR DIFFERENT COLORS
  hMin = 29  # Hue minimum
  sMin = 30  # Saturation minimum
  vMin = 0   # Value minimum (Also referred to as brightness)
  hMax = 179 # Hue maximum
  sMax = 255 # Saturation maximum
  vMax = 255 # Value maximum
  # Set the minimum and max HSV values to display in the output image using numpys' array function. We need the numpy array since OpenCVs' inRange function will use those.
  lower = np.array([hMin, sMin, vMin])
  upper = np.array([hMax, sMax, vMax])
  # Create HSV Image and threshold it into the proper range.
  hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # Converting color space from BGR to HSV
  mask = cv2.inRange(hsv, lower, upper) # Create a mask based on the lower and upper range, using the new HSV image
  # Create the output image, using the mask created above. This will perform the removal of all unneeded colors, but will keep a black background.
  output = cv2.bitwise_and(image, image, mask=mask)
  # Add an alpha channel, and update the output image variable
  *_, alpha = cv2.split(output)
  dst = cv2.merge((output, alpha))
  output = dst
  # Resize the image to 512, 512 (This can be put into a variable for more flexibility), and update the output image variable.
  dim = (512, 512)
  output = cv2.resize(output, dim)
  # Generate a random file name using a mini helper function called randomString to write the image data to, and then save it in the processed_folder path, using the generated filename.
  file_name = randomString(5)   ‘.png’
  cv2.imwrite(processed_folder   ‘/’   file_name, output)

接下来是一个非常简单的功能,可以正确地完成工作。再次强调,使用阈值可以提供更好的结果。我们需要讨论的最后一件事是mini helper函数,该函数为文件名生成随机字符串。

代码语言:javascript复制
def randomString(length):
  letters = string.ascii_lowercase
  return ‘’.join(random.choice(letters) for i in range(length))

这是一个简单的功能。它使用“string”库获取字母,然后根据我们传入的长度加入随机选择的字符。传入5的长度将生成5个字符的字符串。

整个程序的处理结果如下所示:

0 人点赞