【问题标题】:Crop colour image according to OTSU threshold根据 OTSU 阈值裁剪彩色图像
【发布时间】:2021-04-01 11:41:22
【问题描述】:

我有一张彩色图像,我已成功对其灰度形式应用 OTSU 阈值方法以获得饼干的轮廓:

原彩色图片:

OTSU 阈值图像:

我想做的是从彩色图像中仅提取 OTSU 阈值图像黑色部分内的像素,并将其保存为新图片。到目前为止,我尝试使用 BITWISE_NOT 方法进行提取,并使用“thresh_inv”作为掩码,但这只会产生此图像(灰度 + 额外黑色背景)。我还尝试使用精明的轮廓方法来识别饼干圈的粗略轮廓,然后在空白图像上绘制轮廓,以希望尝试将其覆盖在原始彩色图片上。这也不起作用。

这是我到目前为止的代码,我非常感谢任何帮助,因为我已经尝试了很长时间。

import numpy as np
import cv2 as cv2

picture = cv2.imread('Cropped_6.png',0)
blurred_picture = cv2.GaussianBlur(picture, (15,15), cv2.BORDER_DEFAULT)
# canny_picture = cv2.Canny(blurred_picture, 41,41)
# cv2.imshow('Blurred', canny_picture)

# Simple Thresholding
threshold, thresh = cv2.threshold(blurred_picture, 105, 255, cv2.THRESH_OTSU)
# contours, hierarchies = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
thresh_inv = cv2.bitwise_not(thresh)
foreground = cv2.bitwise_and(picture, picture, mask=thresh_inv)

cv2.imwrite('Attempt_1.png',foreground)

# cv2.drawContours(blank_picture, contours[:0], -1, (0,0,255), 1)
cv2.imshow('Original', picture)
cv2.waitKey(0) 

这是我最终得到的结果的一个示例(只是在包含它的矩形中具有透明背景的饼干,因为 afaik 甚至圆形都存储为矩形图像):

想要的结果:

【问题讨论】:

  • 你能描述或模拟一下你的预期结果吗?
  • 完成,感谢您的建议。

标签: python python-3.x opencv opencv3.0 opencv-python


【解决方案1】:

第一次将图像加载为 rgb。然后将其转换为二进制。 因为它有 3 个通道,所以你需要堆叠你的掩码以形成一个具有 3 个通道的阵列 然后对它们进行二进制和操作。

试试:

import numpy as np
import cv2 as cv2
import matplotlib.pyplot as plt

picture_rgb = cv2.imread('cropped6.png',1)
picture = cv2.cvtColor(picture_rgb, cv2.COLOR_BGR2GRAY)

blurred_picture = cv2.GaussianBlur(picture, (15,15), cv2.BORDER_DEFAULT)
# canny_picture = cv2.Canny(blurred_picture, 41,41)
# cv2.imshow('Blurred', canny_picture)

# Simple Thresholding
threshold, thresh = cv2.threshold(blurred_picture, 105, 255, cv2.THRESH_OTSU)
# contours, hierarchies = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
thresh_inv = cv2.bitwise_not(thresh)
stacked = np.dstack((thresh_inv,thresh_inv,thresh_inv))
img = cv2.bitwise_and(picture_rgb, stacked)
foreground = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
foreground[np.all(foreground == (0, 0, 0), axis=-1)] = (255,255,255)

cv2.imwrite('Attempt_1.png',foreground)

# # cv2.drawContours(blank_picture, contours[:0], -1, (0,0,255), 1)
# cv2.imshow('Original', picture)
# cv2.waitKey(0) 
plt.imshow(foreground, cmap='gray')

透明化:(来源:how to make white pixels transparent

from PIL import Image

img = Image.fromarray(np.uint8(foreground)).convert('RGBA')
img = img.convert("RGBA")
datas = img.getdata()

newData = []
for item in datas:
    if item[0] == 255 and item[1] == 255 and item[2] == 255:
        newData.append((255, 255, 255, 0))
    else:
        newData.append(item)

img.putdata(newData)
img.save("img2.png", "PNG")

【讨论】:

  • 啊,我明白了,非常感谢您的解释!有什么办法可以在没有黑色背景的情况下保存“前景”而不是透明(空白)?
  • 是的,我很快就会更新我的答案,只需要解决一件事。
  • @Veja_Du:我已经更新了我的答案。如果有帮助,请将其标记为可接受的解决方案。
  • 非常感谢,非常感谢您的帮助!
猜你喜欢
  • 2021-10-02
  • 1970-01-01
  • 2016-05-04
  • 2012-10-08
  • 1970-01-01
  • 1970-01-01
  • 2020-01-25
  • 2020-06-26
  • 2022-10-15
相关资源
最近更新 更多