TypeError:src不是一个numpy数组,也不是标量

liz*_*ard 11 python opencv numpy image-processing python-2.7

    gray_image = cv2.cvtColor(contrast, cv2.COLOR_BGR2GRAY)

TypeError: src is not a numpy array, neither a scalar
Run Code Online (Sandbox Code Playgroud)

我目前正在努力解决这个问题,任何帮助将不胜感激.如评论中所述,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)
Run Code Online (Sandbox Code Playgroud)

alk*_*asm 9

PIL几乎完全面向对象,因此大多数函数都返回对象.

例如:

>>> image = Image.open('img6.png')
>>> type(image)
<class 'PIL.PngImagePlugin.PngImageFile'>
Run Code Online (Sandbox Code Playgroud)

PIL Image是一个类(因此是大写),因此它返回一个对象.因此,如果图像是一个对象,它可能具有属性,如图像数据,图像的高度/宽度等,以及内置方法,如.show()显示图像.您可以阅读PIL Image类的文档以获取更多信息.

所以你要将类传递给期望数组的函数.那里有问题.解决此问题的一种方法是使用数据将数据读入numpy数组image.getdata(),这是访问PIL中像素值的常用方法.

但是,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'>
Run Code Online (Sandbox Code Playgroud)

好极了!现在我们从图像中得到一个数组.但重要的是,PIL像大多数其他库一样读取RGB图像,但OpenCV实际上使用BGR通道排序.因此,如果您打算使用OpenCV以依赖于其颜色的方式编写,显示或修改图像,则需要确保交换第一个和最后一个通道.

只留下一个问题......处理对比度调整.ContrastImageEnhance模块返回一个对象:

>>> contrast = ImageEnhance.Contrast(image)
>>> type(contrast)
<class 'PIL.ImageEnhance.Contrast'>
Run Code Online (Sandbox Code Playgroud)

但这会返回一个Contrast对象,而不是一个Image对象.实际上你的代码甚至没有修改过图像; 您所做的就是创建增强器对象.你必须调用一种方法来实际执行对比度调整(以及你想要它的强度因素).检查ImageEnhance文档:

所有增强类都实现了一个通用接口,包含一个方法:

enhance(factor)

返回增强的图像.

参数: factor - 控制增强的浮点值.因子1.0总是返回原始图像的副本,较低的因子意味着较少的颜色(亮度,对比度等),而较高的值则更多.此值没有限制.

返回类型: Image

现在,这个方法返回一个Image,所以我们可以运行np.asarray()结果.所以最终的管道将是这样的:

  1. 将图像加载到Image类中
  2. 创建对比度增强对象
  3. 调用enhance(factor)对比度增强对象和返回值将是另一个Image
  4. 获得对比度调整后的图像数据的numpy数组
  5. 从RGB转换为BGR顺序
  6. 正常使用

输入图片:

输入图像

>>> 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()
Run Code Online (Sandbox Code Playgroud)

输出图像:

对比增强图像