Train KNN classifier with several samples OpenCV Python - python

I am working on a logo classifier/recognizer using Python 2.7.5 and OpenCV 2.4.8,
I have several images of the same logo but in different forms and presentations, I would like to train the classifier with that information and at the final recover the name of that logo regardless the form or presentation.
I would like to know how to train a KNN classifier using that information, I have the code that extracts the keypoints and descriptors using SURF, and I am storing that data directly on the hard disk.
def FeatureDetector(cvImage=None, filename=None):
template = dict()
hessian_threshold = 5000
if(filename is not None):
inputImage = cv.imread(filename)
if(cvImage is not None):
inputImage = cvImage
imageGray = cv.cvtColor(inputImage, cv.COLOR_BGR2GRAY)
detector = cv.SURF(hessian_threshold)
keypoints, descriptors = detector.detectAndCompute(imageGray, None, useProvidedKeypoints = False)
template["image"] = inputImage
template["array"] = imageGray
template["keypoints"] = keypoints
template["descriptors"] = descriptors
return template
def saveKeypoints(filename, keypoints):
kArray = []
for point in keypoints:
keypoint = (point.pt, point.size, point.angle, point.response, point.octave, point.class_id)
kArray.append(keypoint)
with open(filename, "wb") as outputFile:
pickle.dump(kArray, outputFile)
return
def detection(logoName, extension, show=False):
imagePath = PATHS["logos"] + logoName + "/"
if(os.path.exists(imagePath)):
count = 1
while(True):
filename = imagePath + str(count) + "." + extension
if(not os.path.exists(filename)):
print "[!] File '%s' not found, the end of sequence was reached"%(filename)
break
temp = FeatureDetector(filename = filename)
saveKeypoints(PATHS["keypoints"] + inputName + "/" + str(count) + ".kp", temp["keypoints"])
np.save(PATHS["descriptors"] + inputName + "/" + str(count) + ".npy", temp["descriptors"])
np.save(PATHS["arrays"] + inputName + "/" + str(count) + ".npy", temp["array"])
if(show):
showFeatures(filename, temp)
print "[O] Processed '%s'"%(filename)
count += 1
else:
print "[X] Logo not found\n"
return
Then, I have another script that load the data and trains the KNN but only with one form of a logo. I would like to train the classifier with all the forms of the logo, using all the keypoints and descriptors that I have and recover only one result.
def loadKeypoints(path):
keypoints = []
try:
with open(PATHS["keypoints"] + path + ".kp", "rb") as inputFile:
kArray = pickle.load(inputFile)
for point in kArray:
feature = cv.KeyPoint(
x=point[0][0],
y=point[0][1],
_size=point[1],
_angle=point[2],
_response=point[3],
_octave=point[4],
_class_id=point[5]
)
keypoints.append(feature)
except:
return False
return keypoints
def loadSURF():
global TEMPLATES, LOGOS
for logo in LOGOS:
TEMPLATES[logo] = list()
count = 1
while(True):
path = "%s/%d"%(logo, count)
keypoints = loadKeypoints(path)
if(not keypoints):
print "[!] Template for '%s' not found, the end of sequence was reached"%(path)
break
descriptors = np.load(PATHS["descriptors"] + path + ".npy")
array = np.load(PATHS["arrays"] + path + ".npy")
template = {
"keypoints": keypoints,
"descriptors": descriptors,
"array": array
}
print "[O] Template loaded from %s"%(path)
TEMPLATES[logo].append(template)
count += 1
return
def SURFCompare(temp, image):
samples = temp["descriptors"]
responses = np.arange(len(temp["keypoints"]), dtype=np.float32)
knn = cv.KNearest()
knn.train(samples, responses)
for template in TEMPLATES:
pattern = TEMPLATES[template]
for t in pattern:
for h, des in enumerate(t["descriptors"]):
des = np.array(des,np.float32).reshape((1,128))
retval, results, neigh_resp, dists = knn.find_nearest(des,1)
res, dist = int(results[0][0]), dists[0][0]
if dist < 0.1: # draw matched keypoints in red color
color = (0,0,255)
print template
else: # draw unmatched in blue color
color = (255,0,0)
#Draw matched key points on original image
x,y = temp["keypoints"][res].pt
center = (int(x),int(y))
cv.circle(image,center,2,color,-1)
return True
Is that possible?
Is the KNN classifier the best approaching or there are another better options? Also I am thinking on use a FLANN matcher.
I don't know if it is the best options because actually I'm only recongnize one logo in one form but I expect to have the possibility of recognize more than one logo in several forms each one.
Thanks in advance.

Related

How to output filename after loading the file in Python?

I am doing a CNN project to estimate pitch from a spectrogram. The project is already finished and waiting to be presented to my institution, but I would like to improve a little detail to my work.
CNN that I have built must be tested using test (val) datas. I store the data in Google Drive (I build my CNN using Google Colab), and before doing testing with do_test method, I have to load the data. Path are given in the code snippet below.
I am able to load the data. The loaded data is then tested, but my problem is, I do not know which file that I have loaded. Testing result is exported to a Python DataFrame. DataFrame example output is attached here.
I want to put the filename of each file loaded and then put it to Dataframe output result, so I will know each output of a specific file. Right now, I can only know the overall data from 1 song without knowing which file is which (see DataFrame). What should I add to my code to get the filenames? Should I modify image_data code in function get_image_and_label?
Some (I hope) useful items:
Folder containing image. Folder link is given here
Folder containing labels can be accessed here
DataFrame output screenshot
Method do_test. This method is used to execute testing.
model = Sequential()
song_titles = "014_twinkle_twinkle 017_old_mcdonald 020_happy_birthday 022_brother_john 030_london_bridge".split()
image_data_train_global_path = "./drive/MyDrive/1117002_Code Skripsi/Dataset/Dataset TA_1_spectrograms/spectrogram_B_2/train/"
image_data_test_global_path = "./drive/MyDrive/1117002_Code Skripsi/Dataset/Dataset TA_1_spectrograms/spectrogram_B_2/val/"
label_global_path = "./drive/MyDrive/1117002_Code Skripsi/Dataset/Dataset TA_2_label_floor/"
def do_test():
for title in song_titles:
print("Song title: ", title)
label_and_image_test = load_image_and_label(title, process='test') # this is where I load my data.
images_test, labels_test = populate_test_data(label_and_image_test)
X_test, y_test = label_processing(images_test, labels_test)
y_pred = model.predict(X_test)
song_number = 0
unique_pitch_result = []
pitch_class_result = []
distance_result = []
while song_number <= (len(y_pred)-1):
label_sequence = []
for i in y_pred[song_number]:
max = np.max(i)
ind = np.argmax(i)
label_sequence.append(ind)
result_pitch_sequence = [k for element in label_sequence for k,v in unique_pitch_dictionary.items() if element == v]
unique_pitch = np.unique(result_pitch_sequence)
unique_pitch = unique_pitch.tolist()
if (title=="014_twinkle_twinkle"):
s1 = s1_014_twinkle
elif (title=="017_old_mcdonald"):
s1 = s1_017_mcd
elif (title=="020_happy_birthday"):
s1 = s1_020_hbd
elif (title=="022_brother_john"):
s1 = s1_022_john
elif (title=="030_london_bridge"):
s1 = s1_030_london
cost_matrix = DTW.dtw_cost_matrix(s1, result_pitch_sequence)
distance = DTW.dtw_distance(cost_matrix)
pitch_class = [v for element in unique_pitch for k,v in pitch_class_dictionary.items() if element == k]
unique_pitch_result.append(unique_pitch)
pitch_class_result.append(pitch_class)
distance_result.append(distance)
song_number+=1
print("+"*100)
df = DTW.test_result_dataframe(unique_pitch_result, pitch_class_result, distance_result, song_number)
print(df)
filename = title + " " + str(epochs) + " " + str(learning_rate) + " dataframe.xlsx"
df.to_excel(filename)
print("*"*120)
Function load_image_and_label. This is used to get data path, then execute file loading from directory.
def load_image_and_label(title, process):
print("Title: ", title)
label_specific_path = label_global_path + title
if (process == "train-test"):
image_data_train_specific_path = image_data_train_global_path + title
image_training_data = get_image_and_label(image_data_train_specific_path, label_specific_path)
image_data_test_specific_path = image_data_test_global_path + title
image_testing_data = get_image_and_label(image_data_test_specific_path, label_specific_path)
if (process == "train-test"):
return image_training_data, image_testing_data
else:
return image_testing_data
Function get_image_and_label. This is where I try to get my files. I think I have to modify something here to output the filename.
def get_image_and_label(image_path, label_path):
print("Getting image data from: ", image_path)
image_data = [] # contains array of loaded image and its label. Maybe, should I add code to append the filename here?
tm = time.time()
for img_item in os.listdir(image_path): #for every image in path
try:
img_array = cv2.imread(os.path.join(image_path, img_item))
# preprocess image
spectrogram_preprocessing = resize_recolor_spectrogram(img_array)
# imread to array
spectrogram_preprocessing = np.array(spectrogram_preprocessing)
# image shape - transpose
spectrogram_preprocessing = np.transpose(spectrogram_preprocessing)
# extract image labels
label = extract_pitch_label(os.path.join(label_path, img_item))
image_data.append([spectrogram_preprocessing, label]) # add image data and its label to image_data array. What code should I add here to get filename?
except Exception as e:
raise e
print("Got "+str(len(image_data))+" images from " + image_path + " in "+str(time.time() - tm)+ " seconds")
print("-"*110)
return image_data
This is the output if I have succeeded in loading my data.
Song title: 014_twinkle_twinkle
Title: 014_twinkle_twinkle
Getting image data from: ./drive/MyDrive/1117002_Code Skripsi/Dataset/Dataset TA_1_spectrograms/spectrogram_B_2/val/014_twinkle_twinkle
Got 32 images from ./drive/MyDrive/1117002_Code Skripsi/Dataset/Dataset TA_1_spectrograms/spectrogram_B_2/val/014_twinkle_twinkle in 0.29237914085388184 seconds
---------------------------------------------------------------------------------------------------------
I have found the solution. it turns out that at this loop declaration:
for img_item in os.listdir(image_path):
img_item is actually the filename, and I do not need to add any more code.

AttributeError: 'bytes' object has no attribute 'read'

I am working on this face recognition system.I have a folder with subfolders that has face images inside it. I am trying to loop through all the subfolders that consists of images and use my 'align_face' function that detects the face and crops and aligns all the images in subfolders. It then has to save all the aligned and cropped in another folder
I have tried this:
def align_face(imagePath):
image = face_recognition.load_image_file(imagePath)
face_locations = face_recognition.face_locations(image)
face_landmarks = face_recognition.face_landmarks(image)
if len(face_locations) == 0:
print("Couldn't detect face for pid {} in path {}".format(Id,imagePath))
return []
if len(face_locations) > 1:
return []
else:
(top, right, bottom, left) = face_locations[0]
desiredWidth = (right - left)
desiredHeight = (bottom - top)
leftEyePts = face_landmarks[0]['left_eye']
rightEyePts = face_landmarks[0]['right_eye']
if len(leftEyePts) == 0 or len(rightEyePts) == 0:
print("Couldn't detect both eyes for pid {} in path {}".format(Id,imagePath))
return []
else:
leftEyeCenter = np.array(leftEyePts).mean(axis=0).astype("int")
rightEyeCenter = np.array(rightEyePts).mean(axis=0).astype("int")
leftEyeCenter = (leftEyeCenter[0],leftEyeCenter[1])
rightEyeCenter = (rightEyeCenter[0],rightEyeCenter[1])
dY = rightEyeCenter[1] - leftEyeCenter[1]
dX = rightEyeCenter[0] - leftEyeCenter[0]
angle = np.degrees(np.arctan2(dY, dX))
desiredLeftEye=(0.35, 0.35)
desiredFaceWidth = desiredWidth
desiredFaceHeight = desiredHeight
desiredRightEyeX = 1.0 - desiredLeftEye[0]
dist = np.sqrt((dX ** 2) + (dY ** 2))
desiredDist = (desiredRightEyeX - desiredLeftEye[0])
desiredDist *= desiredFaceWidth
scale = desiredDist / dist
eyesCenter = ((leftEyeCenter[0] + rightEyeCenter[0]) // 2,
(leftEyeCenter[1] + rightEyeCenter[1]) // 2)
M = cv2.getRotationMatrix2D(eyesCenter, angle, scale)
tX = desiredFaceWidth * 0.5
tY = desiredFaceHeight * desiredLeftEye[1]
M[0, 2] += (tX - eyesCenter[0])
M[1, 2] += (tY - eyesCenter[1])
(w, h) = (desiredFaceWidth, desiredFaceHeight)
output = cv2.warpAffine(image, M, (w, h),flags=cv2.INTER_CUBIC)
output = cv2.cvtColor(output, cv2.COLOR_BGR2RGB)
print("images aligned")
return output
#Now that we have defined the face alignmet and cropping, we walk through each subfolder and use the align function
for root, dirs, files in os.walk('<path to subdirectories that has face pictures>'):
for fname in files:
fpath = os.path.join(root, fname)
with open(fpath, 'rb') as f, open('<path to new folder to store cropped and aligned picture>', 'w') as newfile:
data = f.read()
new_data = align_face(data) #Implementing align_face function
newfile.write(new_data)
However, I keep getting an error.
AttributeError: 'bytes' object has no attribute 'read'
Does anyone know why?Any help would be appreciated. Thank you.
Full error is this:
The argument to align_face is the name of the file containing the image data, not the image data. So you don't need to open and read the data in your loop.
for root, dirs, files in os.walk('<path to subdirectories that has face pictures>'):
for fname in files:
fpath = os.path.join(root, fname)
with open('<path to new folder to store cropped and aligned picture>', 'w') as newfile:
new_data = align_face(fpath) #Implementing align_face function
newfile.write(new_data)

Python: delete item from list when difference with previous appended item is small

I'm creating an image popularity algorithm that cuts a video% .mp4 into frames. With the help of AI, the program examines which frames probably display the most beautiful images; the result of this is expressed in 'score'.
This works but I encounter a problem. Because certain frames in a video are very similar, I have many frames with (almost) the same score.
In the end result, a list is generated with [score, frame number]. I want, for example, if 3 items in the list are almost identical frame numbers and therefore (almost) identical scores, I only keep the frame number in the list with the highest score in order to remove duplicates.
It has something to do with this line: result.append((predict(pil_image, model), name))
Here is the code:
import os
import torch
import torchvision.models
import torchvision.transforms as transforms
from PIL import Image
import json
import cv2
def prepare_image(image):
if image.mode != 'RGB':
image = image.convert("RGB")
Transform = transforms.Compose([
transforms.Resize([224, 224]),
transforms.ToTensor(),
])
image = Transform(image)
image = image.unsqueeze(0)
return image
def predict(image, model):
image = prepare_image(image)
with torch.no_grad():
preds = model(image)
score = preds.detach().numpy().item()
print("Picture score: " + str(round(score, 2)) + " | frames left: " +str(framesToDo))
return str(round(score, 2))
if __name__ == '__main__':
model = torchvision.models.resnet50()
model.fc = torch.nn.Linear(in_features=2048, out_features=1)
model.load_state_dict(torch.load('model/model-resnet50.pth', map_location=torch.device('cpu')))
model.eval()
result = []
# In de folder videos are videos saved with the name of 1 until 23
for i in range(1, 23):
vidcap = cv2.VideoCapture('./video/' + str(i) + '.mp4')
succes, vidcap_image = vidcap.read()
count = 0
framestep = 500 #for Stackoverflow example
framesToDo = vidcap.get(cv2.CAP_PROP_FRAME_COUNT)
# while succes and count < max_frames
while succes and count < int(vidcap.get(cv2.CAP_PROP_FRAME_COUNT)): #maximum amount of frames in video
name = str(i) + '_' + str(count)
cv2.imwrite("./frames_saved/" + 'vid' + '_' + name + ".jpg", vidcap_image) # save frame as jpg image
count += framestep # 500 frames further
framesToDo = framesToDo - framestep
cv2_image = cv2.cvtColor(vidcap_image, cv2.COLOR_BGR2RGB)
pil_image = Image.fromarray(cv2_image)
result.append((predict(pil_image, model), name))
succes, vidcap_image = vidcap.read()
result.sort(reverse=False)
print(result)
with open('result.json', 'w') as filehandle:
filehandle.write(json.dumps(result))````
Since there is no reproducible example, you can adapt this to solve your problem, this analyses each frame data and skips unnecessary ones, updates the best values and append new values.
MAX_FRAME_NUMBER_DIFF = 60
MAX_SCORE_DIFF = 0.5
current_frame = count
current_score = predict(pil_image, model)
data = (current_score, current_frame)
if not results:
results.append(data)
else:
last_score, last_frame = results[-1]
is_similar_frame = current_frame - last_frame <= MAX_FRAME_NUMBER_DIFF
is_score_better = current_score > last_score
is_score_way_better = current_score - last_score <= MAX_SCORE_DIFF
if is_similar_frame:
if is_score_better:
if is_score_way_better: # if diff between current score and previous score bigger than MAX_SCORE_DIFF
results.append(data)
else: # current score better than previous but not so better
results[-1] = data # update last value
else: # current score not better than previous
continue # skip this one
else: # if not similar frames
results.append(data)

How to create and save pairwise hamming distances of image perceptual hashes for imput to clustering algorithm

hoping somebody can provide guidance as to how to compute pairwise hamming distance of a bunch of hashes and then cluster them. I don't care so much as to performance as from looking at what I am doing and what I want to do its going to be slow no matter what and its not something that will be repeatedly run over and over.
So...in a nutshell I had mistakenly erased 1000's of photos off a drive and had no backups (I know...bad practise). Using various tools I was able to recover a very high % of them from the drive but was left with hundreds of 1000's of photos. Due to the techniques used for recovering some of the photos (such as file carving) some of the images are corrupt to various degrees, others were identical copies, and yet others were essentially identical visually but byte for byte were different.
What I am looking at doing to help the situation is the following:
check each image and identify if image file is structurally corrupt or not (done)
generate perceptual hashes (fingerprint) for each image so that images can be compared for similarity and clustered (fingerprinting part is done)
calculate the pairwise distance of the fingerprints
cluster the pairwise distance so that similar images can be viewed together to aide manual cleanup
In the script attached you will notice a couple of places I calculate hashes, I will explain as to not cause confusion...
for images that are supported by PIL I generate three hashes, 1st for original image, 2nd is rotated 90 degrees, and 3rd is rotated 180 degrees. This was done so that when the pairwise calculations are done I can account for images that just vary in orientation.
for raw images not supported by PIL I instead favour hashes that are generated from the extracted embedded preview image. I did this instead of using the raw image because in the case of a corrupt raw image file there was a high chance of probability that the preview image was intact due to its smaller size and thus would be better for identifying if the image is similar to others
other place hashes are generated is during a last ditch effort to identify corrupt raw images. I would compare hashes of the extracted/converted raw image to that of the extracted embedded preview image and if the similarity does not meet a defined threshold it is assumed that there is probably corruption of the raw file as a whole.
What I need guidance on is how to accomplish the following:
take the three hashes I have for each image and calculate hamming pairwise distances
for each image comparison keep only the hamming distance that is most similar
feed the results into scipy hierarchical clustering so that I can group similar images
I am just learning Python so that is part of the my challenge... I think from what I have got from google I can do this by first getting the pairwise distances using scipy.spatial.distance.pdist, then process this to keep the most similar distance for each image comparison, then feed this to a scipy clustering function. But I cannot figure how to organize this and provide things in the proper format etc. Can anyone provide some guidance on this?
Here is my current script for reference in case anyone else finds it interesting that I will need to alter for storing some sort of dictionary of hashes or maybe some sort of on disk storage.
from PIL import Image
from PIL import ImageFile
import os, sys, imagehash, pyexiv2, rawpy, re
from tempfile import NamedTemporaryFile
from subprocess import check_call, call
# allow PIL to load truncated images (so that perceptual hashes can be created for truncated/damaged images still)
ImageFile.LOAD_TRUNCATED_IMAGES = True
# image files this script will handle
# PIL supported image formats
stdimageext = ('.jpg','.jpeg', '.bmp', '.png', '.gif', '.tif', '.tiff')
# libraw/ufraw supported formats
rawimageext = ('.nef', '.dng', '.tif', '.tiff')
devnull = open(os.devnull, 'w')
corruptRegex = re.compile(r'_\[.+\]\..{3,4}$')
for root, dirs, files in os.walk(sys.argv[1]):
for filename in files:
ext = os.path.splitext(filename.lower())[1]
filepath = os.path.join(root, filename)
if ext in (stdimageext + rawimageext):
hashes = [None] * 4
print(filename)
# reset corrupt string
corrupt_str = None
if ext in (stdimageext):
metadata = pyexiv2.ImageMetadata(filepath)
metadata.read()
rotate = 0
try:
im = Image.open(filepath)
except:
None
else:
for x in range(3):
hashes[x] = imagehash.dhash(im.rotate(90 * (x + 1)),32)
# use jpeginfo against all jpg images as its pretty accurate
if ext in ('.jpg','.jpeg'):
rc = 0
rc = call(["jpeginfo", "--check", filepath], stdout=devnull, stderr=devnull)
if rc == 1:
corrupt_str = 'JpegInfo'
if corrupt_str is None:
try:
im = Image.open(filepath)
im.verify()
except:
e = sys.exc_info()[0]
corrupt_str = 'PIL_Verify'
else:
try:
im = Image.open(filepath)
im.load()
except:
e = sys.exc_info()[0]
corrupt_str = 'PIL_Load'
# raw image processing
else:
# extract largest embedded preview image first
metadata_orig = pyexiv2.ImageMetadata(filepath)
metadata_orig.read()
if len(metadata_orig.previews) > 0:
preview = metadata_orig.previews[-1]
# save preview to temp file
temp_preview = NamedTemporaryFile()
preview.write_to_file(temp_preview.name)
os.rename(temp_preview.name + preview.extension, temp_preview.name)
rotate = 0
try:
im = Image.open(temp_preview.name)
except:
None
else:
for x in range(4):
hashes[x] = imagehash.dhash(im.rotate(90 * (x + 1)),32)
# close temp file
temp_preview.close()
# try to load raw using libraw via rawpy first,
# generally if libraw can't load it then ufraw extraction would also fail
try:
with rawpy.imread(filepath) as im:
None
except:
e = sys.exc_info()[0]
corrupt_str = 'Libraw_Load'
else:
# as a final last ditch effort compare perceptual hashes of extracted
# raw and embedded preview to detect possible internal corruption
if len(metadata_orig.previews) > 0:
# extract and convert raw to jpeg image using ufraw
temp_raw = NamedTemporaryFile(suffix='.jpg')
try:
check_call(['ufraw-batch', '--wb=camera', '--rotate=camera', '--out-type=jpg', '--compression=95', '--noexif', '--lensfun=none', '--output=' + temp_raw.name, '--overwrite', '--silent', filepath],stdout=devnull, stderr=devnull)
except:
e = sys.exc_info()[0]
corrupt_str = 'Ufraw-conv'
else:
rhash = imagehash.dhash(Image.open(temp_raw.name),32)
# compare preview with raw image and compute the most similar hamming distance (best)
hamdiff = .0
for h in range(4):
# calculate hamming distance to compare similarity
hamdiff = max((256 - sum(bool(ord(ch1) - ord(ch2)) for ch1, ch2 in zip(str(hashes[h]), str(rhash))))/256,hamdiff)
if hamdiff < .7: # raw file is probably corrupt
corrupt_str = 'hash' + str(round(hamdiff*100,2))
# close temp files
temp_raw.close()
print(hamdiff)
print(rhash)
print(hashes[0])
print(hashes[1])
print(hashes[2])
print(hashes[3])
# prefix file if corruption was detected ensuring that existing files already prefixed are re prefixed
mo = corruptRegex.search(filename)
if corrupt_str is not None:
if mo is not None:
os.rename(filepath,os.path.join(root, re.sub(corruptRegex, '_[' + corrupt_str + ']', filename) + ext))
else:
os.rename(filepath,os.path.join(root, os.path.splitext(filename)[0] + '_[' + corrupt_str + ']' + ext))
else:
if mo is not None:
os.rename(filepath,os.path.join(root, re.sub(corruptRegex, '', filename) + ext))
EDITED
Just want to provide an update with what I came up with in the end that seems to work quite nicely for my intended purpose and maybe it will prove useful for other users in a similar situation. The script can still use some polishing but otherwise all the meat is there. As I am green with respect using Python if anyone see something that can improved greatly please let me know.
The script does the following:
attempts to detect image corruption in terms of file structure using various methods. For raw image formats (NEF, DNG, TIF) sometimes I found that a corrupt image could still load fine so I decided to hash both the preview image and an extracted .jpg of the raw image and compare the hashes and if they were not similar enough I assume that image is corrupted in some form.
create perceptual hashes for each image that could be loaded. Three are created for the base file (original, original rotated 90, original rotated 180). In addition, for raw images an additional 3 hashes were created for the extracted preview image, this was done so that in cases where the raw image was corrupted we would still have hashes based on the full image (assuming the preview is fine).
for images that are identified as corrupt they are renamed with a suffix that indicates that are corrupt and what determined it.
Pairwise hamming distances were computed by comparing hashes against all file pairs and stored in a numpy array.
square form of pairwise distances are fed to fastcluster for clustering
output from fastcluster is used to generate a dendrogram to visualize clusters of similar images
I save the numpy array to disk so that I can later rerun the fastcluster/dendrogram part without recomputing the hashes for each file which is slow. This is something I have to alter the script to allow yet....
from PIL import Image
from PIL import ImageFile
import os, sys, imagehash, pyexiv2, rawpy, re
from tempfile import NamedTemporaryFile
from subprocess import check_call, call
import numpy as np
from scipy.cluster.hierarchy import dendrogram
from scipy.spatial.distance import squareform
import fastcluster
import matplotlib.pyplot as plt
# allow PIL to load truncated images (so that perceptual hashes can be created for truncated/damaged images still)
ImageFile.LOAD_TRUNCATED_IMAGES = True
# image files this script will handle
# PIL supported image formats
stdimageext = ('.jpg','.jpeg', '.bmp', '.png', '.gif', '.tif', '.tiff')
# libraw/ufraw supported formats
rawimageext = ('.nef', '.dng', '.tif', '.tiff')
devnull = open(os.devnull, 'w')
corruptRegex = re.compile(r'_\[.+\]\..{3,4}$')
hashes = []
filelist = []
for root, _, files in os.walk(sys.argv[1]):
for filename in files:
ext = os.path.splitext(filename.lower())[1]
relpath = os.path.relpath(root, sys.argv[1])
filepath = os.path.join(root, filename)
if ext in (stdimageext + rawimageext):
hashes_tmp = []
rhash = []
# reset corrupt string
corrupt_str = None
if ext in (stdimageext):
try:
im=Image.open(filepath)
for x in range(3):
hashes_tmp.append(str(imagehash.dhash(im.rotate(90 * x, expand=1),32)))
except:
None
# use jpeginfo against all jpg images as its pretty accurate
if ext in ('.jpg','.jpeg'):
rc = 0
rc = call(["jpeginfo", "--check", filepath], stdout=devnull, stderr=devnull)
if rc == 1:
corrupt_str = 'JpegInfo'
if corrupt_str is None:
try:
im = Image.open(filepath)
im.verify()
except:
e = sys.exc_info()[0]
corrupt_str = 'PIL_Verify'
else:
try:
im = Image.open(filepath)
im.load()
except:
e = sys.exc_info()[0]
corrupt_str = 'PIL_Load'
# raw image processing
if ext in (rawimageext):
# extract largest embedded preview image first
metadata_orig = pyexiv2.ImageMetadata(filepath)
metadata_orig.read()
if len(metadata_orig.previews) > 0:
preview = metadata_orig.previews[-1]
# save preview to temp file
temp_preview = NamedTemporaryFile()
preview.write_to_file(temp_preview.name)
os.rename(temp_preview.name + preview.extension, temp_preview.name)
try:
im = Image.open(temp_preview.name)
for x in range(3):
hashes_tmp.append(str(imagehash.dhash(im.rotate(90 * x,expand=1),32)))
except:
None
# try to load raw using libraw via rawpy first,
# generally if libraw can't load it then ufraw extraction would also fail
try:
im = rawpy.imread(filepath)
except:
e = sys.exc_info()[0]
corrupt_str = 'Libraw_Load'
else:
# as a final last ditch effort compare perceptual hashes of extracted
# raw and embedded preview to detect possible internal corruption
# extract and convert raw to jpeg image using ufraw
temp_raw = NamedTemporaryFile(suffix='.jpg')
try:
check_call(['ufraw-batch', '--wb=camera', '--rotate=camera', '--out-type=jpg', '--compression=95', '--noexif', '--lensfun=none', '--output=' + temp_raw.name, '--overwrite', '--silent', filepath],stdout=devnull, stderr=devnull)
except:
e = sys.exc_info()[0]
corrupt_str = 'Ufraw-conv'
else:
try:
im = Image.open(temp_raw.name)
for x in range(3):
rhash.append(str(imagehash.dhash(im.rotate(90 * x,expand=1),32)))
except:
None
# compare preview with raw image and compute the most similar hamming distance (best)
if len(hashes_tmp) > 0 and len(rhash) > 0:
hamdiff = 1
for rh in rhash:
# calculate hamming distance to compare similarity
hamdiff = min(hamdiff,(sum(bool(ord(ch1) - ord(ch2)) for ch1, ch2 in zip(hashes_tmp[0], rh))/len(hashes_tmp[0])))
if hamdiff > .3: # raw file is probably corrupt
corrupt_str = 'hash' + str(round(hamdiff*100,2))
hashes_tmp = hashes_tmp + rhash
# prefix file if corruption was detected ensuring that existing files already prefixed are re prefixed
mo = corruptRegex.search(filename)
newfilename = None
if corrupt_str is not None:
if mo is not None:
newfilename = re.sub(corruptRegex, '_[' + corrupt_str + ']', filename) + ext
else:
newfilename = os.path.splitext(filename)[0] + '_[' + corrupt_str + ']' + ext
else:
if mo is not None:
newfilename = re.sub(corruptRegex, '', filename) + ext
if newfilename is not None:
os.rename(filepath,os.path.join(root, newfilename))
if len(hashes_tmp) > 0:
hashes.append(hashes_tmp)
if newfilename is not None:
filelist.append(os.path.join(relpath, newfilename))
else:
filelist.append(os.path.join(relpath, filename))
print(len(filelist))
print(len(hashes))
a = np.empty(shape=(len(filelist),len(filelist)))
for hash_idx1, hash in enumerate(hashes):
a[hash_idx1,hash_idx1] = 0
hash_idx2 = hash_idx1 + 1
while hash_idx2 < len(hashes):
ham_dist = 1
for h1 in hash:
for h2 in hashes[hash_idx2]:
ham_dist = min(ham_dist, (sum(bool(ord(ch1) - ord(ch2)) for ch1, ch2 in zip(h1, h2)))/len(h1))
a[hash_idx1,hash_idx2] = ham_dist
a[hash_idx2,hash_idx1] = ham_dist
hash_idx2 = hash_idx2 + 1
print(a)
X = squareform(a)
print(X)
linkage = fastcluster.single(X)
clustdict = {i:[i] for i in range(len(linkage)+1)}
fig = plt.figure(figsize=(25,25))
plt.title('test title')
plt.xlabel('perpetual hash hamming distance')
plt.axvline(x=.15,c='red',linestyle='--')
dg = dendrogram(linkage, labels=filelist, orientation='right', show_leaf_counts=True)
ax = fig.gca()
ax.set_xlim(-.01,ax.get_xlim()[1])
plt.show
plt.savefig('foo1.pdf', bbox_inches='tight', dpi=100)
with open('numpyarray.npy','wb') as f:
np.save(f,a)
It took awhile...but I figured things out eventually and got a script that does a pretty good job of identifying if an image is corrupt and then uses perceptual hashes to try and group similar images together.
from PIL import Image, ImageFile
import os, sys, imagehash, pyexiv2, rawpy, re
from tempfile import NamedTemporaryFile
from subprocess import Popen, PIPE
import shlex
import numpy as np
from scipy.cluster.hierarchy import dendrogram, fcluster
from scipy.spatial.distance import squareform
import fastcluster
#import matplotlib.pyplot as plt
import math
import string
from wand.image import Image as wImage
import wand.exceptions
from io import BytesIO
from datetime import datetime
#import fd_table_status
def redirect_stdout():
print("Redirecting stdout and stderr")
sys.stdout.flush() # <--- important when redirecting to files
sys.stderr.flush()
newstdout = os.dup(1)
newstderr = os.dup(2)
devnull = os.open(os.devnull, os.O_WRONLY)
devnull2 = os.open(os.devnull, os.O_WRONLY)
os.dup2(devnull, 1)
os.dup2(devnull2,2)
os.close(devnull)
os.close(devnull2)
sys.stdout = os.fdopen(newstdout, 'w')
sys.stderr = os.fdopen(newstderr, 'w')
redirect_stdout()
def ct(linkage_matrix,flist,score):
cluster_id = []
for fidx, file_ in enumerate(flist):
link_ = np.where(linkage_matrix[:,:2] == fidx)[0]
if len(link_) == 1:
link = link_[0]
if linkage_matrix[link][2] <= score:
fcluster_idx = str(link).zfill(len(str(len(linkage_matrix))))
while True:
match = np.where(linkage_matrix[:,:2] == link+1+len(linkage_matrix))[0]
if len(match) == 1:
link = match[0]
link_d = linkage_matrix[link]
if link_d[2] <= score:
fcluster_idx = str(match[0]).zfill(len(str(len(linkage_matrix)))) + fcluster_idx
else:
break
else:
break
else:
fcluster_idx = None
cluster_id.append(fcluster_idx)
return cluster_id
def get_exitcode_stdout_stderr(cmd):
"""
Execute the external command and get its exitcode, stdout and stderr.
"""
args = shlex.split(cmd)
proc = Popen(args, stdout=PIPE, stderr=PIPE, close_fds=True)
out, err = proc.communicate()
exitcode = proc.returncode
del proc
return exitcode, out, err
if os.path.isdir(sys.argv[1]):
start_time = datetime.now()
# allow PIL to load truncated images (so that perceptual hashes can be created for truncated/damaged images still)
ImageFile.LOAD_TRUNCATED_IMAGES = True
# image files this script will handle
# PIL supported image formats
stdimageext = ('.jpg','.jpeg', '.bmp', '.png', '.gif', '.tif', '.tiff')
# libraw/ufraw supported formats
rawimageext = ('.nef', '.dng', '.tif', '.tiff')
corruptRegex = re.compile(r'_\[.+\]\..{3,4}$')
groupRegex = re.compile(r'^\[\d+\]_')
ufrawRegex = re.compile(r'Corrupt data near|Unexpected end of file|has the wrong dimensions!|Cannot open file|Cannot decode file|requests a nonexistent image!')
for subdirs,dirs,files in os.walk(sys.argv[1]):
files.clear()
dirs.clear()
for root,_,files in os.walk(subdirs):
print('\n******** Processing files in ' + root)
hashes = []
w_hash = []
w_hash_idx = []
filelist = []
files_ = []
cnt = 0
for f in files:
#cnt = cnt + 1
#if cnt < 10:
files_.append(f)
continue
cnt = 0
for f_idx, fname in enumerate(files_):
e=None
ext = os.path.splitext(fname.lower())[1]
filepath = os.path.join(root, fname)
imformat = ''
hashes_tmp = []
# reset corrupt string
corrupt_str = None
if ext in (stdimageext + rawimageext):
print(str(int(round(((f_idx+1)/len(files_))*100))) + '%' + ' : ' + fname + '....', end='', flush=True)
try:
with wImage(filename=filepath) as im:
imformat = '.' + im.format.lower()
ext = imformat if imformat is not '' else ext
with im.convert('jpeg') as converted:
jpeg_bin = converted.make_blob()
with Image.open(BytesIO(jpeg_bin)) as im2:
hash_image = []
for x in range(3):
print('.',end='',flush=True)
hash_i = str(imagehash.dhash(im2.rotate(90 * x, expand=1),32))
if ''.join(set(hash_i)) != '0':
hash_image.append(hash_i)
if hash_image:
hash_image.append(1)
hashes_tmp.append(hash_image)
except:
e = sys.exc_info()[0]
errcode = str([k for k, v in wand.exceptions.TYPE_MAP.items() if v == e][0]).zfill(3)
if int(errcode[-2:]) in (15,25,30,35,40,50,55):
corrupt_str = 'magick'
finally:
try:
im.close()
except:
pass
try:
im2.close()
except:
pass
if ext in (stdimageext):
try:
with Image.open(filepath) as im:
hash_image = []
for x in range(3):
print('.',end='',flush=True)
hash_i = str(imagehash.dhash(im.rotate(90 * x, expand=1),32))
if ''.join(set(hash_i)) != '0':
hash_image.append(hash_i)
if hash_image:
hash_image.append(2)
hashes_tmp.append(hash_image)
except:
pass
finally:
try:
im.close()
except:
pass
# use jpeginfo against all jpg images as its pretty accurate
if ext in ('.jpg','.jpeg'):
#rc = 0
print('.',end='',flush=True)
cmd = 'jpeginfo --check "' + filepath + '"'
exitcode, out, err = get_exitcode_stdout_stderr(cmd)
#rc = call(["jpeginfo", "--check", filepath], stdout=DEVNULL, stderr=DEVNULL, close_fds=True)
if exitcode == 1:
corrupt_str = 'JpegInfo' if corrupt_str == None else corrupt_str
#del rc
if corrupt_str is None:
try:
with Image.open(filepath) as im:
print('.',end='',flush=True)
im.verify()
except:
e = sys.exc_info()[0]
corrupt_str = 'PIL_Verify' if corrupt_str == None else corrupt_str
else:
try:
with Image.open(filepath) as im:
print('.',end='',flush=True)
temp = im.copy()
im.load()
except:
e = sys.exc_info()[0]
corrupt_str = 'PIL_Load' if corrupt_str == None else corrupt_str
finally:
try:
temp.close()
except:
pass
try:
im.close()
except:
pass
finally:
try:
im.close()
except:
pass
try:
temp.close()
except:
pass
# raw image processing
if ext in (rawimageext):
print('.',end='',flush=True)
# try to load raw using libraw via rawpy first,
# generally if libraw can't load it then ufraw extraction would also fail
if corrupt_str == None:
try:
with rawpy.imread(filepath) as raw:
rgb = raw.postprocess(use_camera_wb=True)
temp_raw = NamedTemporaryFile(suffix='.jpg')
Image.fromarray(rgb).save(temp_raw.name)
with Image.open(temp_raw.name) as im:
hash_image = []
for x in range(3):
print('.',end='',flush=True)
hash_i = str(imagehash.dhash(im.rotate(90 * x, expand=1),32))
if ''.join(set(hash_i)) != '0':
hash_image.append(hash_i)
if hash_image:
hash_image.append(3)
hashes_tmp.append(hash_image)
except(rawpy.LibRawFatalError):
e = sys.exc_info()[1]
corrupt_str = 'Libraw_FE'
except(rawpy.LibRawNonFatalError):
e = sys.exc_info()[1]
corrupt_str = 'Libraw_NFE'
except:
#print(sys.exc_info())
corrupt_str = 'Libraw'
finally:
try:
im.close()
except:
pass
try:
temp_raw.close()
except:
pass
try:
raw.close()
except:
pass
if corrupt_str == None:
# as a final last ditch effort compare perceptual hashes of extracted
# raw and embedded preview to detect possible internal corruption
# extract and convert raw to jpeg image using ufraw
temp_raw = NamedTemporaryFile(suffix='.jpg')
#rc = 0
cmd = 'ufraw-batch --wb=camera --rotate=camera --out-type=jpg --compression=95 --noexif --lensfun=none --auto-crop --output=' + temp_raw.name + ' --overwrite "' + filepath + '"'
print('.',end='',flush=True)
exitcode, out, err = get_exitcode_stdout_stderr(cmd)
if exitcode == 1 or ufrawRegex.search(str(err)) is not None:
corrupt_str = 'Ufraw' if corrupt_str is None else corrupt_str
tmpfilesize = os.stat(temp_raw.name).st_size
if tmpfilesize > 0:
try:
with Image.open(temp_raw.name) as im:
hash_image = []
for x in range(3):
print('.',end='',flush=True)
hash_i = str(imagehash.dhash(im.rotate(90 * x, expand=1),32))
if ''.join(set(hash_i)) != '0':
hash_image.append(hash_i)
if hash_image:
hash_image.append(4)
hashes_tmp.append(hash_image)
except:
pass
finally:
try:
im.close()
except:
pass
try:
temp_raw.close()
except:
pass
# attempt to extract preview images
imfile = filepath
try:
with pyexiv2.ImageMetadata(imfile) as metadata_orig:
metadata_orig.read()
#for i,p in enumerate(metadata_orig.previews):
if metadata_orig.previews:
preview = metadata_orig.previews[-1]
# save preview to temp file
temp_preview = NamedTemporaryFile()
preview.write_to_file(temp_preview.name)
os.rename(temp_preview.name + preview.extension, temp_preview.name)
try:
with Image.open(temp_preview.name) as im:
hash_image = []
for x in range(3):
print('.',end='',flush=True)
hash_i = str(imagehash.dhash(im.rotate(90 * x, expand=1),32))
if ''.join(set(hash_i)) != '0':
hash_image.append(hash_i)
if hash_image:
hash_image.append(5)
hashes_tmp.append(hash_image)
except:
pass
finally:
try:
temp_preview.close()
except:
pass
try:
im.close()
except:
pass
except:
pass
finally:
try:
metadata_orig.close()
except:
pass
# compare hashes for all images that were found or extracted and find most dissimilar hamming distance (worst)
if len(hashes_tmp) > 1:
#print('checking_hashes')
print('.',end='',flush=True)
scores = []
for h_idx, hash in enumerate(hashes_tmp):
i = h_idx + 1
while i < len(hashes_tmp):
ham_dist = 1
for h1 in hash[:-1]:
for h2 in hashes_tmp[i][:-1]:
ham_dist = min(ham_dist, (sum(bool(ord(ch1) - ord(ch2)) for ch1, ch2 in zip(h1, h2)))/len(h1))
if (hash[-1] == 5 and hashes_tmp[i][-1] != 5) or (hash[-1] != 5 and hashes_tmp[i][-1] == 5):
scores.append([ham_dist,hash[-1],hashes_tmp[i][-1]])
i = i + 1
if scores:
worst = sorted(scores, key = lambda x: x[0])[-1]
if worst[0] > 0.3:
worst1 = str(worst[1])
worst2 = str(worst[2])
corrupt_str = 'hash' + str(round(worst[0]*100,2)) + '_' + worst1 + '-' + worst2 if corrupt_str == None else corrupt_str
# prefix file if corruption was detected ensuring that existing files already prefixed are re prefixed
mo = corruptRegex.search(fname)
newfilename = None
if corrupt_str is not None:
print('Corrupt: ' + corrupt_str)
if mo is not None:
newfilename = re.sub(corruptRegex, '_[' + corrupt_str + ']', fname) + ext
else:
newfilename = os.path.splitext(fname)[0] + '_[' + corrupt_str + ']' + ext
else:
print('OK!')
if mo is not None:
newfilename = re.sub(corruptRegex, '', fname) + ext
# remove group index from name if present, this will be assigned in the next step if needed
newfilename = newfilename if newfilename is not None else fname
mo = groupRegex.search(newfilename)
if mo is not None:
newfilename = re.sub(groupRegex, '', newfilename)
if hashes_tmp:
# set function unduplicates flattened list
hashes.append(set([item for sublist in hashes_tmp for item in sublist[:-1]]))
filelist.append([root,fname,newfilename, len(hashes_tmp)])
print('******** Grouping similar images... ************')
if len(hashes) > 1:
scores = []
for h_idx, hash in enumerate(hashes):
i = h_idx + 1
while i < len(hashes):
ham_dist = 1
for h1 in hash:
for h2 in hashes[i]:
ham_dist = min(ham_dist, (sum(bool(ord(ch1) - ord(ch2)) for ch1, ch2 in zip(h1, h2)))/len(h1))
scores.append(ham_dist)
i = i + 1
X = np.array(scores)
linkage = fastcluster.single(X)
w_hash_idx = [el_idx for el_idx, el in enumerate(filelist) if el[3] > 0]
w_hash = [filelist[i] for i in w_hash_idx]
test=ct(linkage,[el[2] for el in w_hash],.2)
for i, prfx in enumerate(test):
curfilename = w_hash[i][2]
mo = groupRegex.search(curfilename)
newfilename = None
if prfx is not None:
if mo is not None:
newfilename = re.sub(groupRegex, '[' + prfx + ']_', curfilename)
else:
newfilename = '[' + prfx + ']_' + curfilename
else:
if mo is not None:
newfilename = re.sub(groupRegex, '', curfilename)
# if newfilename is not None:
filelist[w_hash_idx[i]][2] = newfilename if newfilename is not None else curfilename
#fig = plt.figure(figsize=(25,25))
#plt.title(root)
#plt.xlabel('perpetual hash hamming distance')
#plt.axvline(x=.15,c='red',linestyle='--')
#dg = dendrogram(linkage, labels=[el[2] for el in w_hash], orientation='right', show_leaf_counts=True)
#ax = fig.gca()
#ax.set_xlim(-.02,ax.get_xlim()[1])
#plt.show
#plt.savefig(os.path.join(root,'dendrogram.pdf'), bbox_inches='tight', dpi=100)
w_hash.clear()
w_hash_idx.clear()
print('******** Renameing file if applicable... ************')
for fr in filelist:
if fr[1] != fr[2]:
#print(fr[1] + ' -- ' + fr[2])
path = fr[0]
os.rename(os.path.join(path,fr[1]),os.path.join(path,fr[2]))
filelist.clear()
duration = datetime.now() - start_time
days = divmod(duration.total_seconds(), 86400) # Get days (without [0]!)
hours = divmod(days[1], 3600) # Use remainder of days to calc hours
minutes = divmod(hours[1], 60) # Use remainder of hours to calc minutes
seconds = divmod(minutes[1], 1) # Use remainder of minutes to calc seconds
print("Time to complete: %d days, %d:%d:%d" % (days[0], hours[0], minutes[0], seconds[0]))

OpenCV Python Unsupported response type

I am currently writing a Bag Of Words analyser using OpenCV and Python. I have been able to extract the info from the images, learn but the problem is the training part. As a baseline, I am using this and translating it into Python, but I get to the learn part and when it should train the classifier it fails saying that it has an unsupported response type (I assume labels is not in the correct format). I have tried a bit of everything but I cannot get it to work. Any ideas?
import cv2
import os
import numpy as np
dictSize = 1000
retries = 1
flags = cv2.KMEANS_PP_CENTERS
tc = (cv2.TERM_CRITERIA_MAX_ITER, 10, 0.001)
matcher = cv2.DescriptorMatcher_create("FlannBased")
extractor = cv2.DescriptorExtractor_create("SURF")
detector = cv2.FeatureDetector_create("SURF")
bowTrainer = cv2.BOWKMeansTrainer(dictSize,tc,retries,flags)
bowDE = cv2.BOWImgDescriptorExtractor(extractor,matcher)
def extractTrainingVocabulary(path):
global bowTrainer
global extractor
lst=os.listdir(path)
for i in range(0,len(lst)):
if lst[i][0] != ".":
fullPath = path + lst[i]
print "Processing Image " + fullPath
img = cv2.imread(fullPath)
if not (len(img) == 0):
keypoints = detector.detect(img)
if (len(keypoints) == 0):
print "Warning! Could not find any keypoints in image " + fullPath
else:
# Returns 2 vars. The underscore is used to discard the first one
_,features = extractor.compute(img,keypoints)
bowTrainer.add(features)
else:
print "Could not read image " + fullPath
def extractBOWDescriptor(path, descriptors, labels):
global bowTrainer
global extractor
lst=os.listdir(path)
for i in range(0,len(lst)):
if lst[i][0] != ".":
fullPath = path + lst[i]
print "Processing Image " + fullPath
img = cv2.imread(fullPath)
if not (len(img) == 0):
keypoints = detector.detect(img)
if (len(keypoints) == 0):
print "Warning! Could not find any keypoints in image " + fullPath
else:
bowDescriptor = bowDE.compute(img,keypoints)
# descriptors.append(bowDescriptor)
#np.vstack((descriptors,bowDescriptor))
descriptors = np.vstack((descriptors,bowDescriptor))
#labels.append(lst[i][:-4])
labels = np.vstack((labels,float(lst[i][:-4])))
else:
print "Could not read image " + fullPath
return labels, descriptors
def main():
global bowDE
# LEARN
print "Creating Dict..."
extractTrainingVocabulary("./testImages/")
descriptors = bowTrainer.getDescriptors()
print "Clustering " + str(len(descriptors)) + " features. This might take a while..."
dictionary = bowTrainer.cluster()
print "Done clustering"
# EXTRACT
size1 = 0,dictSize
trainingData = np.zeros(size1,dtype=np.float32)
size2 = 0,1
labels = np.zeros(size2,dtype=np.float32)
bowDE.setVocabulary(dictionary)
labels,trainingData = extractBOWDescriptor("./evalImages/",trainingData,labels)
print(trainingData)
print(labels)
print "Training classifier"
size3 = len(trainingData),len(trainingData[0])
responseData = np.zeros(size3,dtype=np.float32)
classifier = cv2.NormalBayesClassifier()
classifier.train(trainingData,labels)
main()
EDIT
as per #berak's suggestion, I changed the following:
labels = np.vstack((labels,float(lst[i][:-4]))) -> labels = np.vstack((labels,int(lst[i][:-4])))
labels = np.zeros(size2,dtype=np.float32) -> labels = np.zeros(size2,dtype=np.int32)
Unfortunately still fails. Now I get the following:
error: (-5) There is only a single class in function cvPreprocessCategoricalResponses

Categories