我正在从此图像中提取白色条纹,但很想在“实验室”图像中看到基本的Sobel运算符的输出。尽管我很高兴看到黑色条纹达到预期的效果,但我无法证明'np.hstack'运算符后面发生了什么。如果仅在'sobel'上应用plt.imshow(),则不会得到相同的输出。所需的输出是包含白色条纹的二进制图像。
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()
EDIT1
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()
plt.axis('off')
plt.title('hstack')
plt.imshow(imgs_comb,cmap='gray') #<<<<<Different output but is generic when tried with different images
plt.show()
答案 0 :(得分:1)
您的applySobel
方法期望将灰度(单通道)图像作为输入,但是您正在使用lab
(三通道图像)作为输入,这将对所有3个通道应用Sobel滤波。意外的结果来自plt.imshow
将Sobel过滤的Lab通道解释为图像的RGB通道。
如果仅使用l
,a
或b
(或将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('https://i.stack.imgur.com/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()
这将产生以下图像:
Sobel过滤器用于边缘检测,因此它将仅突出显示边缘而不是整个条纹。因此,如果您的目标是突出显示整个条纹,则直接阈值L通道会更有效:
# Directly threshold L-channel and plot
plt.imshow(cv2.threshold(l, 220, 255, cv2.THRESH_BINARY)[1], cmap='gray')
plt.show()
结果:
还请注意,由于尺寸不同,您不能直接使用np.hstack
将3通道图像与灰度/二进制图像组合。首先使用np.stack((img,) * 3, axis=-1)
将单通道图像转换为3通道图像。
答案 1 :(得分:1)
np.hstack
函数不会更改您的数据,但会更改图像的显示方式。如果将不同范围的图像连接到一个阵列中,则imshow
函数将自动缩放到最大范围。这就是为什么只显示一幅或多幅图像时会有所不同的原因lab
数组的所有通道。也许您只想在l
频道上应用它。但是,如果单独检查l
,a
和b
的范围,您会注意到那里的强度相差很大。sobel
时,imshow
会自动假定您给出的3个通道是RGB数据,这就是为什么您有此奇怪图像的原因。plt.imshow(sobel[:, :, 0])
,则可以得到sobel滤波器的结果,因此可以得到轮廓。