Python 类型错误:src 不是 numpy 数组,也不是标量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45864550/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
TypeError: src is not a numpy array, neither a scalar
提问by lizardwizard
gray_image = cv2.cvtColor(contrast, cv2.COLOR_BGR2GRAY)
TypeError: src is not a numpy array, neither a scalar
I am currently working to solve this, any help would be appreciated. As mentioned in the comments, the PIL image needs to be converted to CV2 accepted format, can anyone provide an explanation using the example given below?
我目前正在努力解决这个问题,任何帮助将不胜感激。正如评论中提到的,PIL 图像需要转换为 CV2 接受的格式,任何人都可以使用下面给出的示例提供解释吗?
import cv2
import numpy as np
from matplotlib import pyplot as plt
from cycler import cycler
from PIL import Image, ImageEnhance
# Loads the image then enhances it
image = Image.open('lineCapture.png')
contrast = ImageEnhance.Contrast(image)
# Reads the enhanced image and converts it to grayscale, creates new file
gray_image = cv2.cvtColor(contrast, cv2.COLOR_BGR2GRAY) //there is a problem here
cv2.imwrite('enhancedGrayscaleLineCapture.png', gray_image)
# Adaptive Gaussian Thresholding
th1 = cv2.adaptiveThreshold(gray_image,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv2.THRESH_BINARY,11,2)
# Otsu's thresholding
ret2,th2 = cv2.threshold(gray_image,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering
blur = cv2.GaussianBlur(gray_image,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# writes enhanced and thresholded img
cv2.imwrite('enhancedGrayscaleThresholdLineCapture.png', th2)
采纳答案by alkasm
PIL is almost completely object oriented, so most functions return objects.
PIL 几乎完全面向对象,因此大多数函数返回对象。
For example:
例如:
>>> image = Image.open('img6.png')
>>> type(image)
<class 'PIL.PngImagePlugin.PngImageFile'>
The PIL Image
is a class (hence the capital) so it returns an object. So if the image is an object, it probably has properties, like the image data, the height/width of the image, and so on, along with built-in methods, like .show()
which will display the image. You can read the docs for the PIL Image
classfor more.
PILImage
是一个类(因此是大写),因此它返回一个对象。因此,如果图像是一个对象,它可能具有属性,如图像数据、图像的高度/宽度等,以及内置方法,例如.show()
将显示图像。您可以阅读 PILImage
类的文档以了解更多信息。
So you're passing classes along to functions which expect arrays. Going to have a problem there. One way to solve this is to read the data into a numpy array using image.getdata()
, which is the usual way to access pixel values in PIL.
因此,您将类传递给需要数组的函数。那里会有问题。解决此问题的一种方法是使用 将数据读入 numpy 数组image.getdata()
,这是访问 PIL 中像素值的常用方法。
However, numpy will automagically convert the Image
into an array for you with a simple command: np.asarray()
.
然而,numpy的它将自动转换Image
到一个数组给你一个简单的命令:np.asarray()
。
>>> image = Image.open('img6.png')
>>> type(image)
<class 'PIL.PngImagePlugin.PngImageFile'>
>>> image_data = np.asarray(image)
>>> type(image_data)
<class 'numpy.ndarray'>
Yay! Now we have an array from the image. Importantly though, PIL reads images as RGB images like most other libraries, but OpenCV actually uses BGR channel ordering. So you'll need to make sure you swap the first and last channels around if you're going to use OpenCV to write, display, or modify images in a way that depends on their color.
好极了!现在我们有一个来自图像的数组。重要的是,PIL 像大多数其他库一样将图像读取为 RGB 图像,但 OpenCV 实际上使用 BGR 通道排序。因此,如果您要使用 OpenCV 以取决于图像颜色的方式编写、显示或修改图像,则需要确保交换第一个和最后一个通道。
Only one problem left...dealing with the contrast adjustment. Contrast
from the ImageEnhance
module returns an object as well:
只剩下一个问题……处理对比度调整。Contrast
从ImageEnhance
模块也返回一个对象:
>>> contrast = ImageEnhance.Contrast(image)
>>> type(contrast)
<class 'PIL.ImageEnhance.Contrast'>
But this returns a Contrast
object, and not an Image
object. In fact your code hasn't even modified the image; all you have done is create the enhancer object. You have to call a method to actually perform the contrast adjustment (and a factor of how strong you want it to be). Check the docs for ImageEnhance:
但这会返回一个Contrast
对象,而不是一个Image
对象。事实上,您的代码甚至没有修改图像;您所做的就是创建增强器对象。您必须调用一个方法来实际执行对比度调整(以及您希望它有多强的一个因素)。检查ImageEnhance的文档:
All enhancement classes implement a common interface, containing a single method:
enhance(factor)
Returns an enhanced image.
Parameters:
factor
– A floating point value controlling the enhancement. Factor 1.0 always returns a copy of the original image, lower factors mean less color (brightness, contrast, etc), and higher values more. There are no restrictions on this value.Return type:
Image
所有增强类都实现了一个通用接口,包含一个方法:
enhance(factor)
返回增强图像。
参数:
factor
– 控制增强的浮点值。因子 1.0 始终返回原始图像的副本,较低的因子意味着较少的颜色(亮度、对比度等),较高的值意味着更多。这个值没有限制。返回类型:
Image
Now, thismethod returns an Image
, so we can run np.asarray()
on the result. So the final pipeline would be something like:
现在,此方法返回一个Image
,因此我们可以运行np.asarray()
结果。所以最终的管道将是这样的:
- Load image into
Image
class - Create contrast enhancement object
- Invoke
enhance(factor)
on the contrast enhancement object and the return val will be anotherImage
class - Get a numpy array of the contrast adjusted image data
- Convert from RGB to BGR order
- Use normally
- 将图像加载到
Image
类中 - 创建对比度增强对象
enhance(factor)
在对比度增强对象上调用,返回的 val 将是另一个Image
类- 获取对比度调整后的图像数据的 numpy 数组
- 从 RGB 转换为 BGR 顺序
- 正常使用
Input Image:
输入图像:
>>> pil_image = Image.open('img6.png')
>>> contrast_enhancer = ImageEnhance.Contrast(pil_image)
>>> pil_enhanced_image = contrast_enhancer.enhance(2)
>>> enhanced_image = np.asarray(pil_enhanced_image)
>>> r, g, b = cv2.split(enhanced_image)
>>> enhanced_image = cv2.merge([b, g, r])
>>> cv2.imshow('Enhanced Image', enhanced_image)
>>> cv2.waitKey()
Output Image:
输出图像:
回答by I.Newton
Thanks to Alexander Reynolds for the great explanation. lizardwizard, since you are not able to figure out the mistake in your code, check this out
感谢亚历山大雷诺兹的精彩解释。lizardwizard,由于您无法找出代码中的错误,请查看此
import cv2
import numpy as np
from matplotlib import pyplot as plt
from cycler import cycler
from PIL import Image, ImageEnhance
# Loads the image then enhances it
image = Image.open('lineCapture.png')
contrast = ImageEnhance.Contrast(image)
img=contrast.enhance(2)
img = np.asarray(img)
r, g, b,a = cv2.split(img)
contrast=cv2.merge([b, g, r])
# Reads the enhanced image and converts it to grayscale, creates new file
gray_image = cv2.cvtColor(contrast, cv2.COLOR_BGR2GRAY) #there is a problem here
# Adaptive Gaussian Thresholding
th1 = cv2.adaptiveThreshold(gray_image,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv2.THRESH_BINARY,11,2)
# Otsu's thresholding
ret2,th2 = cv2.threshold(th1,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# Otsu's thresholding after Gaussian filtering
blur = cv2.GaussianBlur(th2,(5,5),0)
ret3,th3 = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
# writes enhanced and thresholded img
cv2.imwrite('enhancedGrayscaleThresholdLineCapture.png', th3)