根据 OTSU 阈值裁剪彩色图像
Crop colour image according to OTSU threshold
我有一张彩色图像,我成功地在其灰度形式上应用了 OTSU 阈值法来获得饼干的轮廓:
原始彩色图像:
OTSU 阈值图像:
我想做的是从彩色图像中仅提取 OTSU 阈值图像黑色部分内的像素,并将其另存为新图片。到目前为止,我已经尝试使用 BITWISE_NOT 方法进行提取并使用 'thresh_inv' 作为蒙版,但这只会导致此图像(灰度 + 额外的黑色背景)。我还尝试使用 cannny 轮廓方法来识别饼干圈的粗略轮廓,然后在空白图像上绘制轮廓,希望尝试将其覆盖在原始彩色图片上。这也没有用。
到目前为止,这是我的代码,我将非常感谢任何帮助,因为我已经尝试了很长时间。
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 甚至圆圈都存储为矩形图像):
想要的结果:
1st 将图像加载为 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")
我有一张彩色图像,我成功地在其灰度形式上应用了 OTSU 阈值法来获得饼干的轮廓:
原始彩色图像:
OTSU 阈值图像:
我想做的是从彩色图像中仅提取 OTSU 阈值图像黑色部分内的像素,并将其另存为新图片。到目前为止,我已经尝试使用 BITWISE_NOT 方法进行提取并使用 'thresh_inv' 作为蒙版,但这只会导致此图像(灰度 + 额外的黑色背景)。我还尝试使用 cannny 轮廓方法来识别饼干圈的粗略轮廓,然后在空白图像上绘制轮廓,希望尝试将其覆盖在原始彩色图片上。这也没有用。
到目前为止,这是我的代码,我将非常感谢任何帮助,因为我已经尝试了很长时间。
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 甚至圆圈都存储为矩形图像):
想要的结果:
1st 将图像加载为 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")