用纯白填充图像蒙版中的数字

2024-04-25 04:55:33 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个白色背景上有文字的图像,另一个我想把文字叠加在上面

我已经计算出了两幅图像之间的absdiff,现在有了一个用于混合这两幅图像的遮罩

img1 * mask + img2 * (1-mask)

我的问题是我的文本的轮廓是黑色的,但文本的中心是白色的。但是,一些图像的背景也是白色的

所以我现在生成的掩码是这样的

enter image description here

这是我的目标

enter image description here

有人建议用纯白填充数字吗

我试着将文本的颜色变成浅灰色,并使用np.where,但我似乎无法让它发挥作用

编辑-我拥有的图像有:

MatMattLIB(如果需要)的空白轴

enter image description here

更新后的条形图将转换为图像。(背景图片)-请忽略它们只是用于测试的图片!!哈

enter image description here

我需要覆盖在条形图上的文本框。(上面要覆盖的图像)

enter image description here


Tags: 图像文本目标mask中心轮廓img1条形图
2条回答

对于使用Python/OpenCV呈现的图像,有一种方法可以做到这一点

  • 读取输入
  • 变灰
  • 门槛
  • 找到外部轮廓并在黑色背景上绘制白色填充轮廓
  • 反转阈值
  • 用黑色填充洪水,然后是白色,然后是黑色
  • 找到外部轮廓并在先前的白色填充轮廓图像上绘制黑色填充轮廓
  • 保存结果

输入:

enter image description here

import cv2
import numpy as np

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

# convert gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold saturation image
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# get outer contours and draw filled ones as white on black background
cntrs = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
result1 = np.zeros_like(img)
for c in cntrs:
    cv2.drawContours(result1, [c], 0, (255,255,255), -1)

# invert thresh
thresh2 = 255 - thresh
hh, ww = thresh2.shape

# floodfill thresh2 with black then white then black again
mask = np.zeros([hh + 2, ww + 2], np.uint8)
thresh2 = cv2.floodFill(thresh2, mask, (0,0), 0, 0, 0, flags=8)[1]
mask = np.zeros([hh + 2, ww + 2], np.uint8)
thresh2 = cv2.floodFill(thresh2, mask, (0,0), 255, 0, 0, flags=8)[1]
mask = np.zeros([hh + 2, ww + 2], np.uint8)
thresh2 = cv2.floodFill(thresh2, mask, (0,0), 0, 0, 0, flags=8)[1]

# get outer contours of these holes and draw filled ones as black
cntrs2 = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs2 = cntrs2[0] if len(cntrs2) == 2 else cntrs2[1]
result2 = result1.copy()
for c in cntrs2:
    cv2.drawContours(result2, [c], 0, (0,0,0), -1)

# antialias if desired as follows:

# blur threshold image
result3 = result2.copy()
result3 = cv2.GaussianBlur(result3, (0,0), sigmaX=9, sigmaY=9, borderType = cv2.BORDER_DEFAULT)

# normalize so min=0 and max=255
result3 = cv2.normalize(result3, None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

# stretch so that 255 -> 255 and 127.5 -> 0
result3 = skimage.exposure.rescale_intensity(result3, in_range=(127.5,255), out_range=(0,255))  

# save output image
cv2.imwrite('1970_thresh1.png', thresh)
cv2.imwrite('1970_thresh2.png', thresh2)
cv2.imwrite('1970_result1.png', result1)
cv2.imwrite('1970_result2.png', result2)
cv2.imwrite('1970_result3.png', result3)

# display IN and OUT images
cv2.imshow('thresh', thresh)
cv2.imshow('thresh2', thresh2)
cv2.imshow('result1', result1)
cv2.imshow('result2', result2)
cv2.imshow('result3', result3)
cv2.waitKey(0)
cv2.destroyAllWindows()


阈值:

enter image description here

白色填充轮廓:

enter image description here

洪水填充后的反向阈值(内孔):

enter image description here

二进制结果:

enter image description here

抗锯齿结果:

enter image description here

如果希望保留非0或255的外部像素,那么在Python/OpenCV中还有另一种方法

输入:

enter image description here

  • 读取输入
  • 变灰
  • 门槛
  • 反转阈值
  • 用黑色填塞
  • 获取外部轮廓,并将其绘制为黑色背景上的白色填充轮廓
  • 回到倒转的门槛,用黑色、白色、黑色填充,得到“洞”
  • 从中获取外部轮廓,并在先前的白色填充轮廓上绘制为黑色
  • 将此结果添加到输入图像
  • 保存结果


import cv2
import numpy as np

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

# convert gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold saturation image
thresh1 = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# invert thresh
thresh1 = 255 - thresh1
hh, ww = thresh1.shape

# floodfill thresh1 with black
mask = np.zeros([hh + 2, ww + 2], np.uint8)
thresh1 = cv2.floodFill(thresh1, mask, (0,0), 0, 0, 0, flags=8)[1]

# get outer contours and draw filled ones as white on black background
cntrs = cv2.findContours(thresh1, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs = cntrs[0] if len(cntrs) == 2 else cntrs[1]
result1 = np.zeros_like(img)
for c in cntrs:
    cv2.drawContours(result1, [c], 0, (255,255,255), -1)

# floodfill thresh1 with black then white then black again
thresh2 = thresh1.copy()
mask = np.zeros([hh + 2, ww + 2], np.uint8)
thresh2 = cv2.floodFill(thresh2, mask, (0,0), 0, 0, 0, flags=8)[1]
mask = np.zeros([hh + 2, ww + 2], np.uint8)
thresh2 = cv2.floodFill(thresh2, mask, (0,0), 255, 0, 0, flags=8)[1]
mask = np.zeros([hh + 2, ww + 2], np.uint8)
thresh2 = cv2.floodFill(thresh2, mask, (0,0), 0, 0, 0, flags=8)[1]

# get outer contours of these holes and draw filled ones as black on copy of result1 and input
cntrs2 = cv2.findContours(thresh2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cntrs2 = cntrs2[0] if len(cntrs2) == 2 else cntrs2[1]
result2 = result1.copy()
for c in cntrs2:
    cv2.drawContours(result2, [c], 0, (0,0,0), -1)

# add result2 to input
result3 = cv2.add(result2,img)

# save output image
cv2.imwrite('1970_thresh1b.png', thresh1)
cv2.imwrite('1970_thresh2b.png', thresh2)
cv2.imwrite('1970_result1b.png', result1)
cv2.imwrite('1970_result2b.png', result2)
cv2.imwrite('1970_result3b.png', result3)

# display IN and OUT images
cv2.imshow('thresh1', thresh1)
cv2.imshow('thresh2', thresh2)
cv2.imshow('result1', result1)
cv2.imshow('result2', result2)
cv2.imshow('result3', result3)
cv2.waitKey(0)
cv2.destroyAllWindows()


洪水填充后的第一个阈值图像:

enter image description here

来自第一个阈值图像的填充轮廓:

enter image description here

洪水填充后的第二个阈值图像(“孔”):

enter image description here

在上一个轮廓图像上以黑色绘制的孔轮廓:

enter image description here

最终结果将最后结果添加到输入:

enter image description here

相关问题 更多 >