问题
cv2.error: OpenCV(4.2.0) c:\projects\opencv
python\opencv\modules\imgproc\src\color.simd_helpers.hpp:92: error:
(-2:Unspecified error) in function '__cdecl cv::impl::`anonymous-
namespace'::CvtHelper<struct cv::impl::`anonymous
namespace'::Set<3,4,-1>,struct cv::impl::A0xe227985e::Set<1,-1,-1>,struct
cv::impl::A0xe227985e::Set<0,2,5>,2>::CvtHelper(const class
cv::_InputArray
&,const class cv::_OutputArray &,int)
> Invalid number of channels in input image:
> 'VScn::contains(scn)'
> where
> 'scn' is 1
img = cv2.cvtColor(images, cv2.COLOR_BGR2GRAY)
this line gives me error
hello everyone i am new to use opencv, now i am doing project on image classification
my complete code as follows
from flask import Flask, request
from flask_restful import Api, Resource
import sys, os
from myconstants1 import path_logs, path_resources
from logConfig1 import setup_logger
import pathlib, pycountry, cv2, pickle, random, PIL, sys
from pathlib import Path
import pathlib as pl
import numpy as np
from sklearn.model_selection import train_test_split
import pandas as pd
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Dense
from keras.optimizers import Adam
from keras.utils.np_utils import to_categorical
from keras.layers import Flatten, Dropout
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.preprocessing.image import ImageDataGenerator
from PIL import Image, ImageOps
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
logger = setup_logger('/modelTrain', path_logs+'/modelTrain.log')
app = Flask(__name__)
api = Api(app)
path = sys.path
path = Path(__file__).parent
print("path2", path)
class HandleRequest5(Resource):
y_validation = ""
x_test = ""
x_validation = ""
x_train = ""
@classmethod
def post(cls, json):
data = request.get_json()
json = ({
"Status": "failed",
"message": "ALL fields are mandatory"
})
try:
country_code = data["country_code"].upper()
batch_size = data["batch_size"]
step_per_epoch_val = data["step_per_epoch_val"]
epoch = data["epoch"]
except KeyError:
print(json)
logger.debug(json)
return(json)
try:
country = pycountry.countries.get(alpha_3 = data["country_code"].upper()).name.lower()
print("country1", country)
logger.debug(f'country1 : {country}')
country = country.split()
country =("_".join(country))
print("country : ", country)
logger.debug(f"country : {country}")
alpha_2 = pycountry.countries.get(alpha_3 = data["country_code"].upper()).alpha_2
print("alpha_2 : ", alpha_2)
logger.debug(f"alpha_2 : {alpha_2}")
except AttributeError:
jsonify1 = {
"status": "invalid",
"message" : "Invalid country_code"
}
print("invalid country_code")
logger.debug({
"status": "invalid",
"message" : "Invalid country_code"
})
return jsonify1
# path = rf'{path}/{country}' # folder with all class folders
labelFile = rf'{path_resources}/{country}/labels.csv'
imageDimensions = (99, 200, 3)
print("imageDimensions:", imageDimensions)
testRatio = 0.2 # if 1000 images split will 200 for testing
validationRatio = 0.2
print("line 91 is going to execute")
cls.importImages( cls,testRatio , validationRatio , imageDimensions ,country , labelFile)
def importImages(cls, testRatio, validationRatio, imageDimensions, country, labelFile):
count = 0
images = []
classNo = []
p = pl.Path(f'{path_resources}/{country}')
mylist = [x for x in p.iterdir() if x.is_dir()]
print("mylist1", mylist)
print("total classs detected :", len(mylist))
noofClasses = len(mylist)
print("noofClasses:", noofClasses)
print("importing classes...")
for x in range(0, len(mylist)):
myPicList = os.listdir(os.path.join(str(path_resources), str(country)+'//'+str(count)))
print("myPicList1:", myPicList)
#for y in myPicList:
#print(os.path.join(path, str(count), y))
#curImg = cv2.imread((str(path_resources)+"/"+str(count)+"//"+y))
for y in myPicList:
print(os.path.join(path_resources, country, str(count)+y))
curImg = cv2.imread(f"{path_resources}{country}/{str(count)}//{y}")
images.append(curImg)
classNo.append(count)
print(count, end = " ")
count+=1
print(" ")
images = np.array(images, dtype=np.uint8)
images = np.array(images)
print("line 128")
print(images.shape)
#images = np.append(images,4)
#images = images.append((Image.fromarray(images, dtype=np.float32).convert('RGB') / 255.))
# image = Image.fromarray(images)
#images = images.convert("RGB")
classNo = np.array(classNo)
cls.splitData(cls,images, classNo, testRatio, validationRatio , imageDimensions, labelFile, noofClasses)
return images, classNo, noofClasses
# split data #
def splitData(cls, images, classNo, testRatio, validationRatio , imageDimensions, labelFile, noofClasses):
x_train, x_test, y_train, y_test = train_test_split(images, classNo, test_size = testRatio)
x_train, x_validation, y_train, y_validation = train_test_split(x_train, y_train , test_size = validationRatio)
# to check if no of images matches to number of labels for each data set
print("data shapes...")
print("train : ", end = "");print(x_train.shape, y_train.shape)
print("validation :", end = ""); print(x_validation.shape, y_validation.shape)
print("test :", end = ""); print(x_test.shape, y_test.shape)
assert (x_train.shape[0] == y_train.shape[0]), "the no of images is not equal to the no of labels in training set"
assert (x_validation.shape[0] == y_validation.shape[0]), "the no of images is not equal to the no of labels in validation set"
assert (x_test.shape[0] == y_test.shape[0]), "the no of images is not equal to the no of labels in test set"
#print(x_train.shape)
assert (x_train.shape[1:] == (imageDimensions)), "the dimension of training images are wrong"
assert (x_validation.shape[1:] == (imageDimensions)), "the dimension of validation images are wrong"
assert (x_test.shape[1:] == (imageDimensions)), "the dimension of test images are wrong"
data = pd.read_csv(labelFile)
cls.grayscale(cls, images, x_train, x_validation, x_test, y_train, y_validation, y_test )
return images, x_train, x_validation, x_test, y_train, y_validation, y_test
# preprocessing the image #
def grayscale(cls,images, x_train, x_validation, x_test, y_train, y_validation, y_test):
#images = ImageOps.grayscale(images)
images = cv2.cvtColor(images, cv2.COLOR_BGR2GRAY)
cls.equalize(images)
return images
def equalize(images):
img = cv2.equalizeHist(images)
cls.preprocessing(img, grayscale, equalize)
return img
def preprocessing(cls, img, grayscale, equalize, x_train, x_validation, x_test, y_train, y_test, y_validation):
img = grayscale(img) #convert to grayscale
img = equalize(img) #standardize the lightining of an image
img = img/255 # to normaize value between 0 and 1 instead of 0 to 255
return img , x_train, x_validation, x_test, y_train, y_test, y_validation
x_train = np.array(list(map(preprocessing, x_train))) # to iterate and preprocess all images
x_validation = np.array(list(map(preprocessing, x_validation)))
x_test = np.array(list(map(preprocessing, x_test)))
#cv2.imshow("grayscale images", x_train[random.randint(0, len(x_train)-1)]) #to check if training is done properly
# add a depth of 1 #
x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], x_train.shape[2], 1)
x_validation = x_validation.reshape(x_validation .shape[0], x_validation .shape[1], x_validation .shape[2], 1)
x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], x_test.shape[2], 1)
def dataAugmentation(cls, x_train, y_train, noofClasses):
# augmentation of images to make it more generic #
dataGen = ImageDataGenerator(width_shift_range = 0.1,
height_shift_range = 0.1,
zoom_range = 0.2,
shear_range = 0.1,
rotation_range = 10)
dataGen.fit(x_train)
batches = dataGen.flow(x_train, y_train, batch_size = 20)
x_batch, y_batch = next(batches)
# to show augmentated image sample
#fig, axs = plt.subplots(24, 2, figsize = (20, 5))
#fig.tight_layout()
#print(axs)
#print("axs0:",axs[0])
#print("axs1:",axs[1])
#for i in range(10):
#axs[i].imshow(x_batch[i].reshape(imageDimensions[0], imageDimensions[1]))
#axs[0][1].imshow(x_batch[i].reshape(imageDimensions[0], imageDimensions[1]))
#axs[i].axis("off")
#axs[0][1].axis('off')
#plt.show()
y_train = to_categorical(y_train, noofClasses)
y_validation = to_categorical(y_validation, noofClasses)
y_test = to_categorical(y_test, noofClasses)
cls.splitData(y_validations)
cls.myModel(noofClasses)
# convolution neural network #
def myModel(cls, noofClasses, country):
no_of_filters = 60
size_of_filter = (5,5) #this is kernal that move around the image to get the features
size_of_filter2 = (3,3)
size_of_pool = (2,2)
no_of_nodes = 200
model = Sequential()
model.add(Conv2D(no_of_filters, size_of_filter, input_shape = (imageDimensions[0], imageDimensions[1], 1), activation = "relu"))
model.add(Conv2D(no_of_filters, size_of_filter, activation = "relu"))
model.add(MaxPooling2D(pool_size = size_of_pool))
model.add(Conv2D(no_of_filters//2, size_of_filter2, activation = "relu"))
model.add(Conv2D(no_of_filters//2, size_of_filter2, activation = "relu"))
model.add(Dropout(0.5))
model.add(Flatten())
model.add(Dense(no_of_nodes, activation = "relu"))
model.add(Dropout(0.5))
# model.add(Flatten())
model.add(Dense(noofClasses, activation = "softmax"))
# compile model #
model.compile(Adam(lr = 0.001), loss = "categorical_crossentropy", metrics = ["accuracy"])
return model
# train #
model = myModel()
print(model.summary())
history = model.fit_generator (dataGen.flow(x_train, y_train, batch_size = batch_size_val), steps_per_epoch = steps_per_epoch_val, epochs = epoch_val, validation_data = (x_train, y_train))
# plot #
plt.figure(1)
plt.plot(history.history["loss"])
plt.plot(history.history["val_loss"])
plt.legend(["training", "validation"])
plt.title("loss")
plt.xlabel("epoch")
plt.figure(2)
plt.plot(history.history["accuracy"])
plt.plot(history.history["val_accuracy"])
plt.legend(["training", "accuracy"])
plt.title("accuracy")
plt.xlabel("epoch")
#plt.show()
score = model.evaluate(x_test, y_test, verbose = 0)
print("test score: ", score[0])
print("test accuracy: ", score[1])
###############################################################
#store the model as pickle object #
#save_path = rf'{path}/{country}'
pickle_out = open(rf"{path_resources}/{country}.p", "wb")
#model = model.save(rf'{country}_{epoch_val}.h5')
pickle.dump(model, pickle_out)
pickle_out.close()
print(rf"{country}_model saved...")
cv2.waitKey(0)
api.add_resource(HandleRequest5, '/modelTrain')
if __name__ == ' __main__ ':
app.run(debug = False)
回答1:
As suggested in the comments, you have two ways to do this. You can either iterate through each image and run the cv2.cvtColor
method or you can use the formula to convert from RGB to grayscale directly. OpenCV uses the SMPTE Rec. 601 conversion formula, which is:
Y = 0.299*R + 0.587*G + 0.114*B
Let's cover both methods.
Method #1
Create a new 3D array that is 336 x 99 x 200
then iterate through each image in your 4D array, convert then set it to the corresponding location in the output.
images_gray = np.zeros(images.shape[:-1], dtype=images.dtype)
for i, img in enumerate(images):
images_gray[i] = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
Method #2 - Use the conversion formula directly
I would argue that this method is the most efficient, mainly because what I will suggest that you do is compute this vectorized:
coeffs = np.array([0.114, 0.587, 0.229])
images_gray = (images.astype(np.float) * coeffs).sum(axis=-1)
images_gray = images_gray.astype(images.dtype)
Two things to note: The first is that the weights for each of the RGB values are reversed due to OpenCV reading images in BGR format. The second is that I have temporarily cast the images to floating-point precision so that you maintain the most accuracy possible due to the floating-point coefficients. We then convert the resulting output back to the same precision as your input images. Finally, what the above code will do is for every pixel for every image, we will multiply each colour pixel by the weights seen in the conversion formula, then sum over the values. The above code will do it in a vectorized way with no loops.
Minor note regarding image classification
I noticed in the comments thread above that you are using this to perform image classification. If you plan on using a deep learning framework, you usually need to maintain a singleton dimension to reflect the channel dimension so that you can properly do broadcasting in the forward pass of the network. In other words, you must have a 336 x 99 x 200 x 1
array. For method #1, simply declare your output array to have the four dimensions, but in the loop you will need to add a singleton dimension to the end of your array by using np.newaxis
.
images_gray = np.zeros(images.shape, dtype=images.dtype)
for i, img in enumerate(images):
images_gray[i] = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)[..., np.newaxis]
For method #2, you can add keepdims=True
in the sum
call:
coeffs = np.array([0.114, 0.587, 0.229])
images_gray = (images.astype(np.float) * coeffs).sum(axis=-1, keepdims=True)
images_gray = images_gray.astype(images.dtype)
来源:https://stackoverflow.com/questions/65388627/invalid-number-of-channels-in-input-image-error-using-opencv