gpt4 book ai didi

python - Sobel 运算符的 Opencv 意外输出

转载 作者:行者123 更新时间:2023-12-01 00:21:54 27 4
gpt4 key购买 nike

我正在从该图像中提取白色条纹,但很想看到“Lab”图像中基本 Sobel 算子的输出。尽管我很高兴看到黑色条纹是理想的结果,但我无法证明“np.hstack”运算符背后发​​生的事情是合理的。如果 plt.imshow() 仅应用于“sobel”,我不会得到相同的输出。所需的输出是包含白色条纹的二值图像。

enter image description here

import numpy as np
import cv2
import os,sys
from matplotlib import pyplot as plt

def getColorSpaces(image):
rgb = cv2.cvtColor(image,cv2.COLOR_RGB2BGR)
gray = cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
return rgb,gray

def getImageDimnesion(image):
height,width = image.shape[:2]
return height,width

def showImage(image,title,cmap):
plt.imshow(image,cmap=cmap)
plt.axis('off')
plt.title(title)


def splitRGBChannels(image):
red, green, blue= cv2.split(img)
return red, green, blue

def getMagnitude(gray):
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
abs_sobelx = np.absolute(sobelx)
abs_sobely = np.absolute(sobely)
magnitude=np.sqrt(abs_sobelx*abs_sobelx+abs_sobely*abs_sobely)
return magnitude,np.arctan2(abs_sobely,abs_sobelx)


def applySobel(gray):
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
abs_sobelx = np.absolute(sobelx)
abs_sobely = np.absolute(sobely)
return abs_sobelx+abs_sobely


images_path=r'images'
images=os.listdir(images_path)

for im in images[:]:
print(im)
img = cv2.imread(os.path.join(images_path,im))

plt.axis('off')
plt.title('Originial')
plt.imshow(img,cmap='gray')
plt.show()

for im in images[:]:
print(im)
plt.figure(figsize=(12, 12))
img = cv2.imread(os.path.join(images_path,im))

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
lab=cv2.cvtColor(img, cv2.COLOR_BGR2LAB)
h,s,v = cv2.split(hsv)
l,a,b = cv2.split(lab)
sobel=applySobel(lab)
imgs_comb = np.hstack([img,lab,sobel])

plt.axis('off')
plt.title('Originial-Lab-Sobel')
plt.imshow(imgs_comb,cmap='gray')
plt.show()

编辑1

plt.axis('off')
plt.title('img')
plt.imshow(img,cmap='gray')
plt.show()

plt.axis('off')
plt.title('lab')
plt.imshow(lab,cmap='gray')
plt.show()

plt.axis('off')
plt.title('sobel')
plt.imshow(sobel,cmap='gray')
plt.show()

enter image description here

plt.axis('off')
plt.title('hstack')
plt.imshow(imgs_comb,cmap='gray') #<<<<<Different output but is generic when tried with different images
plt.show()

enter image description here

最佳答案

您的 applySobel 方法需要灰度(单 channel )图像作为输入,但您使用 lab (3 channel 图像)作为输入,这将应用 Sobel -过滤到所有 3 个 channel 。意想不到的结果来自 plt.imshow 将 Sobel 过滤的 Lab channel 解释为图像的 RGB channel 。

如果您仅使用 lab(或将 Lab 转换为灰色的不同方法),它就会按预期工作。但是,结果将不是二进制的。要使其成为二进制,您可以应用一个阈值(使用cv2.threshold(img,threshold,max_value,cv2.THRESH_BINARY)。下面是一个示例:

import cv2
import numpy as np
from matplotlib import pyplot as plt
from skimage.io import imread


def applySobel(gray):
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=3)
abs_sobelx = np.absolute(sobelx)
abs_sobely = np.absolute(sobely)
return abs_sobelx + abs_sobely


# Load the image (RGB)
img = imread('/image/qN2ta.jpg')

# Convert to Lab and split channels
lab = cv2.cvtColor(img, cv2.COLOR_RGB2LAB)
l, a, b = cv2.split(lab)

# Plot image of Lab-channels
plt.title('L, a, and b channel')
plt.imshow(np.hstack([l, a, b]), cmap='gray')
plt.show()

# Apply Sobel to L-channel (the other channels have low contrast)
l_sobel = applySobel(l)

# Plot result
plt.title('Sobel-filtered L-channel')
plt.imshow(l_sobel, cmap='gray')
plt.show()

# Make result binary by applying a threshold
sobel_thresh = np.uint8(cv2.threshold(l_sobel, 500, 255, cv2.THRESH_BINARY)[1])

# Plot binary result
plt.title('Thresholded Sobel-filtered L-channel')
plt.imshow(sobel_thresh, cmap='gray')
plt.show()

这会产生以下图像:

LAB channels Sobel-filtered L-channel Thresholded Sobel-filtered L-channel

Sobel 滤波器用于边缘检测,因此它只会突出显示边缘而不是整个条纹。因此,如果您的目标是突出显示整个条纹,直接对 L channel 进行阈值处理会更有效:

# Directly threshold L-channel and plot
plt.imshow(cv2.threshold(l, 220, 255, cv2.THRESH_BINARY)[1], cmap='gray')
plt.show()

结果:

enter image description here

另请注意,由于尺寸不同,您不能直接使用 np.hstack 将 3 channel 图像与灰度/二值图像组合。首先使用np.stack((img,) * 3, axis=-1)将单 channel 图像转换为3 channel 图像。

关于python - Sobel 运算符的 Opencv 意外输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58897645/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com