web-dev-qa-db-fra.com

TypeError: src n'est pas un tableau numpy, ni un scalaire

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

TypeError: src is not a numpy array, neither a scalar

Je travaille actuellement pour résoudre ce problème, toute aide serait appréciée. Comme mentionné dans les commentaires, l'image PIL doit être convertie au format accepté CV2, quelqu'un peut-il fournir une explication en utilisant l'exemple ci-dessous?

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)
10
lizardwizard

PIL est presque complètement orienté objet, donc la plupart des fonctions renvoient des objets.

Par exemple:

>>> image = Image.open('img6.png')
>>> type(image)
<class 'PIL.PngImagePlugin.PngImageFile'>

Le PIL Image est une classe (d'où la capitale) donc il retourne un objet. Donc, si l'image est un objet, elle a probablement des propriétés, comme les données d'image, la hauteur/largeur de l'image, etc., ainsi que des méthodes intégrées, comme .show() qui affichera l'image . Vous pouvez lire les documents de la classe PIL Image pour en savoir plus.

Vous transmettez donc des classes à des fonctions qui attendent des tableaux. Va avoir un problème là-bas. Une façon de résoudre ce problème consiste à lire les données dans un tableau numpy en utilisant image.getdata() , qui est la manière habituelle d'accéder aux valeurs des pixels dans PIL.

Cependant , numpy convertira automatiquement le Image en un tableau pour vous avec une simple commande: 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! Maintenant, nous avons un tableau de l'image. Mais surtout, PIL lit les images sous forme d'images RVB comme la plupart des autres bibliothèques, mais OpenCV utilise en fait l'ordre des canaux BGR. Vous devrez donc vous assurer d'échanger les premier et dernier canaux si vous souhaitez utiliser OpenCV pour écrire, afficher ou modifier des images d'une manière qui dépend de leur couleur.

Un seul problème à gauche ... concernant le réglage du contraste. Contrast du module ImageEnhance renvoie également un objet:

>>> contrast = ImageEnhance.Contrast(image)
>>> type(contrast)
<class 'PIL.ImageEnhance.Contrast'>

Mais cela renvoie un objet Contrast et non un objet Image. En fait, votre code n'a même pas modifié l'image; tout ce que vous avez fait est de créer l'objet Enhancer. Vous devez appeler une méthode pour effectuer réellement l'ajustement du contraste (et un facteur de la force que vous souhaitez qu'il soit). Vérifiez les documents pour ImageEnhance :

Toutes les classes d'amélioration implémentent une interface commune, contenant une seule méthode:

enhance(factor)

Renvoie une image améliorée.

Paramètres: factor - Une valeur à virgule flottante contrôlant l'amélioration. Le facteur 1.0 renvoie toujours une copie de l'image d'origine, des facteurs plus faibles signifient moins de couleurs (luminosité, contraste, etc.) et des valeurs plus élevées. Il n'y a aucune restriction sur cette valeur.

Type de retour: Image

Maintenant, la méthode this renvoie un Image, afin que nous puissions exécuter np.asarray() sur le résultat. Ainsi, le pipeline final serait quelque chose comme:

  1. Charger l'image dans la classe Image
  2. Créer un objet d'amélioration du contraste
  3. Appelez enhance(factor) sur l'objet d'amélioration du contraste et la valeur de retour sera une autre classe Image
  4. Obtenez un tableau numpy des données d'image à contraste ajusté
  5. Convertir du RVB au BGR
  6. Utiliser normalement

Image d'entrée:

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()

Image de sortie:

Contrast Enhanced Image

9
alkasm

Merci à Alexander Reynolds pour la grande explication. lizardwizard, puisque vous ne pouvez pas comprendre l'erreur dans votre code, vérifiez ceci

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)
3
I.Newton