Multiprocessing a loop inside another loop - python

This code processes multiple PDFs one at a time. Within each PDF, it is looping through each page using opencv to detect if each page is a 4up page vs 1up page, and if it is a 4up page, the loop appends the index of that page to a list named "ind". Since the order of the pages being processed doesn't matter, I would like to multiprocess the opencv detection. But I'm a complete newb in Python, so can't seem to get it working using Pool function.
This is the original code (single-threaded)
from pdf2image import convert_from_path
import cv2
import numpy as np
pdffiles = 'sample.pdf'
for p in pdffiles:
pages=convert_from_path(pdffiles)
ind = []
for i in range(len(pages)):
page = pages[i]
gray = np.array(page)
gray = cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)
(thresh, bw) = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
edges = cv2.Canny(bw,0,255)
minLineLength=850
lines = cv2.HoughLinesP(image=edges,rho=5,theta=np.pi/90, threshold=1000,lines=np.array([]), minLineLength=minLineLength,maxLineGap=3)
linessub = lines[((lines[:,0,0]>750) & (lines[:,0,0]<950))|((lines[:,0,1]>1000) & (lines[:,0,1]<1200))]
if len(linessub) > 1: ind.append(i)
print(ind)
edit: I've simplified what I posted to just include the section I'm trying to multiprocess. You should be able to run the code on the sample.pdf that I've uploaded here: on this file, the ind that prints should be [1,2]
https://www.dropbox.com/s/g2dvpex7njvon6r/sample.pdf?dl=0

There are 2 ways you can process things simultaneously. Multiprocessing and Threading. You'd have to try which works better for you.
Threading
This is a basis example and to help you on the way.
import threading
results = []
threads = []
def task(arg):
results.append(arg)
for i in range(10):
t = threading.Thread(target=task)
threads.append(t)
t.start()
print results
Below would be an example applied on your code. I couldn't run your example so this isn't tested.
import threading
import timeit
curdir = os.path.dirname(os.path.realpath(__file__))
os.chdir(curdir)
files = os.listdir(curdir)
if os.environ.get('OS','') == 'Windows_NT':
dstdir = os.path.join(curdir, '1up\\')
else:
dstdir = os.path.join(curdir, '1up/')
if not os.path.exists(dstdir):
os.makedirs(dstdir)
pdffiles = [f for f in files if f.endswith('.pdf')]
ind = []
def 4up_detect(pages):
gray = np.array(pages)
gray = cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)
(thresh, bw) = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
edges = cv2.Canny(bw,0,255)
minLineLength=1100
lines = cv2.HoughLinesP(image=edges,rho=5,theta=np.pi/90, threshold=1000,lines=np.array([]), minLineLength=minLineLength,maxLineGap=3)
linessub = lines[((lines[:,0,0]>750) & (lines[:,0,0]<950))|((lines[:,0,1]>1000) & (lines[:,0,1]<1200))]
if len(linessub) > 1:
ind.append(pages)
threads = []
for p in pdffiles:
pages=convert_from_path(p)
t = threading.Thread(target=4up_detect, args=[pages])
threads.append(t)
t.start()
startpg = min(ind)
endpg = max(ind)
page = pages[startpg]
image = np.array(page)
height = int(math.floor(image.shape[0])/2)
width = int(math.floor(image.shape[1])/2)
Multiprocessing
With processing you want to add a shared variable to pass on the results.
A minimal working example can look like this:
import multiprocessing
def task(arg, results):
'''worker function'''
results.append(arg)
manager = multiprocessing.Manager()
results = manager.list()
procs = []
for i in range(10):
p = multiprocessing.Process(target=task, args=(i,results))
procs.append(p)
p.start()
for i in procs:
i.join()
print(results)
This is roughly how that could look in your code. However again, I couldn't run it:
import multiprocessing
import timeit
def 4up_detect(pages, results):
gray = np.array(pages)
gray = cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)
(thresh, bw) = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
edges = cv2.Canny(bw,0,255)
minLineLength=1100
lines = cv2.HoughLinesP(image=edges,rho=5,theta=np.pi/90, threshold=1000,lines=np.array([]), minLineLength=minLineLength,maxLineGap=3)
linessub = lines[((lines[:,0,0]>750) & (lines[:,0,0]<950))|((lines[:,0,1]>1000) & (lines[:,0,1]<1200))]
if len(linessub) > 1:
results.append(pages)
curdir = os.path.dirname(os.path.realpath(__file__))
os.chdir(curdir)
files = os.listdir(curdir)
if os.environ.get('OS','') == 'Windows_NT':
dstdir = os.path.join(curdir, '1up\\')
else:
dstdir = os.path.join(curdir, '1up/')
if not os.path.exists(dstdir):
os.makedirs(dstdir)
pdffiles = [f for f in files if f.endswith('.pdf')]
manager = multiprocessing.Manager()
ind = manager.list()
procs = []
for p in pdffiles:
pages=convert_from_path(p)
p = multiprocessing.Process(target=task, args=(pages, ind))
procs.append(p)
p.start()
for p in procs:
p.join()
startpg = min(ind)
endpg = max(ind)
page = pages[startpg]
image = np.array(page)
height = int(math.floor(image.shape[0])/2)
width = int(math.floor(image.shape[1])/2)

Related

How to make this loop parallel and faster?

I have this set of images from which I want to create a set of sub images with a stride with sub image size of 128*128, original image must be greater than this size (row and column both), I have created the following functions :
def sliding_window(image, stride, imgSize):
height, width, _ = image.shape
img = []
a1 = list(range(0, height-imgSize+stride, stride))
a2 = list(range(0, width-imgSize+stride, stride))
if (a1[-1]+imgSize != height):
a1[-1] = height-imgSize
if (a2[-1]+imgSize != width):
a2[-1] = width-imgSize
for y in a1:
for x in a2:
im1 = image[y:y+imgSize, x:x+imgSize, :]
img.append(np.array(im1))
return img
and the main code snippet from where I call this definition :
im_counter = 0
image_data = []
image_label = []
for cl in file_images:
for img_file in data[cl]:
path = img_path + cl + "/" + img_file
im = image.load_img(path)
im = image.img_to_array(im)
im_counter += 1
if(im_counter % 500 == 0):
print("{} images processed...".format(im_counter))
if (im.shape[0] >= SIZE and im.shape[1] >= SIZE):
img = sliding_window(im, STRIDE, SIZE)
for i in range(len(img)):
if(img[i].shape[2] >=3):
temp_img = img[i]
temp_img = preprocess_input(temp_img)
image_data.append(temp_img)
del temp_img
gc.collect()
image.append(class_dictionary[cl])
Now, the above code snippet takes forever to run on only 3000 images (takes at least 25 hours with utilizing only 1 CPU core), I want to make this faster, I have server access, the CPU has many cores, so can you please suggest a parallelized version of it so that it runs faster ?
NOTE : The sequence of subimages in which it is returned from the original image matters very much, No arbitrary sequence of image is allowed.
Here is a rough outline of something you can try.
def main():
# Create a list of tuples consisting of the file path, and the class
# dictionary info for each of the cl arguments
args = []
for cl in file_images:
for img_file in data[cl]:
path = img_path + cl + "/" + img_file
args.append((path, class_dictionary[cl]))
with multiprocessing.Pool(processes=30) as pool: # or however many processes
image_counter = 0
# Use multiprocessing to call handle_on_image(pathname, info)
# and return the results in order
for images, info in pool.starmap(handle_one_image, args):
# Images is a list of returned images. info is the class_dictionary info that we passed
for image in images:
image_counter += 1
image_data.append(image)
image_label.append(info)
def handle_one_image(path, info):
image_data = []
im = image.load_img(path)
im = image.img_to_array(im)
if (im.shape[0] >= SIZE and im.shape[1] >= SIZE):
img = sliding_window(im, STRIDE, SIZE)
for i in range(len(img)):
if(img[i].shape[2] >=3):
temp_img = img[i]
temp_img = preprocess_input(temp_img)
image_data.append(temp_img)
return image_data, info
else:
# indicate that no images are available
return [], info

Generate individual H5 files for each and every video

My code is about to create an H5 file for Each and Every video in the folder, Extracting the feature from the video and stored into the H5 file.
in Below shown code extraction feature from multi videos and all the features are stored in the single H5 file
H5 file order:
video1:
- feature
video2:
- feature
issues:
How to create an H5 file for every video after a process is done
Code: Create_data.py
import argparse
from utils.generate_dataset import Generate_Dataset
parser = argparse.ArgumentParser(""Welcome you to fraction)
# Dataset options
parser.add_argument('--input', '--split', type=str, help="input video")
parser.add_argument('--output', type=str, default='', help="out data")
args = parser.parse_args()
if __name__ == "__main__":
gen = Generate_Dataset(args.input, args.output)
gen.generate_dataset()
gen.h5_file.close()
Code: Generate_Dataset.py :
import os
from networks.CNN import ResNet
from utils.KTS.cpd_auto import cpd_auto
from tqdm import tqdm
import math
import cv2
import numpy as np
import h5py
import numpy as np
class Generate_Dataset:
def __init__(self, video_path, save_path):
self.resnet = ResNet()
self.dataset = {}
self.video_list = []
self.video_path = ''
self.h5_file = h5py.File(save_path, 'w')
self._set_video_list(video_path)
def _set_video_list(self, video_path):
# import pdb;pdb.set_trace()
if os.path.isdir(video_path):
self.video_path = video_path
fileExt = r".mp4",".avi"
self.video_list = [_ for _ in os.listdir(video_path) if _.endswith(fileExt)]
self.video_list.sort()
else:
self.video_path = ''
self.video_list.append(video_path)
for idx, file_name in enumerate(self.video_list):
self.dataset['video_{}'.format(idx+1)] = {}
self.h5_file.create_group('video_{}'.format(idx+1))
def _extract_feature(self, frame):
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
frame = cv2.resize(frame, (224, 224))
res_pool5 = self.resnet(frame)
frame_feat = res_pool5.cpu().data.numpy().flatten()
return frame_feat
def _get_change_points(self, video_feat, n_frame, fps):
n = n_frame / fps
m = int(math.ceil(n/2.0))
K = np.dot(video_feat, video_feat.T)
change_points, _ = cpd_auto(K, m, 1)
change_points = np.concatenate(([0], change_points, [n_frame-1]))
temp_change_points = []
for idx in range(len(change_points)-1):
segment = [change_points[idx], change_points[idx+1]-1]
if idx == len(change_points)-2:
segment = [change_points[idx], change_points[idx+1]]
temp_change_points.append(segment)
change_points = np.array(list(temp_change_points))
# temp_n_frame_per_seg = []
# for change_points_idx in range(len(change_points)):
# n_frame = change_points[change_points_idx][1] - change_points[change_points_idx][0]
# temp_n_frame_per_seg.append(n_frame)
# n_frame_per_seg = np.array(list(temp_n_frame_per_seg))
# print(change_points)
arr = change_points
list1 = arr.tolist()
list2 = list1[-1].pop(1) #pop [-1]value
print(list2)
print(list1)
print("****************") # [-1][-1] value find and divided by 15
cps_m = math.floor(arr[-1][1]/15)
list1[-1].append(cps_m) #append to list
print(list1)
print("****************") #list to nd array convertion
arr = np.asarray(list1)
print(arr)
arrmul = arr * 15
print(arrmul)
print("****************")
# print(type(change_points))
# print(n_frame_per_seg)
# print(type(n_frame_per_seg))
median_frame = []
for x in arrmul:
print(x)
med = np.mean(x)
print(med)
int_array = med.astype(int)
median_frame.append(int_array)
print(median_frame)
# print(type(int_array))
return arrmul
# TODO : save dataset
def _save_dataset(self):
pass
def generate_dataset(self):
print('[INFO] CNN processing')
for video_idx, video_filename in enumerate(self.video_list):
video_path = video_filename
if os.path.isdir(self.video_path):
video_path = os.path.join(self.video_path, video_filename)
video_basename = os.path.basename(video_path).split('.')[0]
video_capture = cv2.VideoCapture(video_path)
fps = video_capture.get(cv2.CAP_PROP_FPS)
n_frames = int(video_capture.get(cv2.CAP_PROP_FRAME_COUNT))
frame_list = []
picks = []
video_feat = None
video_feat_for_train = None
for frame_idx in tqdm(range(n_frames-1)):
success, frame = video_capture.read()
if frame_idx % 15 == 0:
if success:
frame_feat = self._extract_feature(frame)
picks.append(frame_idx)
if video_feat_for_train is None:
video_feat_for_train = frame_feat
else:
video_feat_for_train = np.vstack((video_feat_for_train, frame_feat))
if video_feat is None:
video_feat = frame_feat
else:
video_feat = np.vstack((video_feat, frame_feat))
else:
break
video_capture.release()
arrmul = self._get_change_points(video_feat, n_frames, fps)
self.h5_file['video_{}'.format(video_idx+1)]['features'] = list(video_feat_for_train)
self.h5_file['video_{}'.format(video_idx+1)]['picks'] = np.array(list(picks))
self.h5_file['video_{}'.format(video_idx+1)]['n_frames'] = n_frames
self.h5_file['video_{}'.format(video_idx+1)]['fps'] = fps
self.h5_file['video_{}'.format(video_idx + 1)]['video_name'] = video_filename.split('.')[0]
self.h5_file['video_{}'.format(video_idx+1)]['change_points'] = arrmul
Expected results :
Folder: video
video_1:
video1.mp4
video2.mp4
Files are in this structure, now read video files and create separate H5 files after the process is over.
For more Code reference
You need to :
remove self.h5_file = h5py.File(save_path, 'w') from __init__()
remove self.h5_file.create_group('video_{}'.format(idx+1)) from _set_video_list()
remove gen.h5_file.close() from main()
change last block of generate_dataset() into something like:
.
video_capture.release()
arrmul = self._get_change_points(video_feat, n_frames, fps)
h5_dir = os.path.dirname(video_path)
h5_full_path = os.path.join(h5_dir, 'video_{}'.format(video_idx+1))
with h5py.File(h5_full_path, 'w') as h5_file:
h5_file['features'] = list(video_feat_for_train)
h5_file['picks'] = np.array(list(picks))
h5_file['n_frames'] = n_frames
h5_file['fps'] = fps
h5_file['video_name'] = video_filename.split('.')[0]
h5_file['change_points'] = arrmul
Please note that your inner video file indices and actual video file name numbers may not match. So I suggest to change
h5_dir = os.path.dirname(video_path)
h5_full_path = os.path.join(h5_dir, 'video_{}'.format(video_idx+1))
from above into
h5_full_path = video_path.split('.')[0] + '.h5'
This will create features file with the name matched to the video file.

Reading Multiple Images One at a Time

I have multiple images stored at my desktop that need to be processed one at a time by Tensorflow. My problem is that I don't know how to create a loop to accomplish the individual reading and processing of images.
I found on this site the code that enables the reading of multiple images stored locally. I placed the code where I thought I would work but it didn't.
The results obtained by the code below, out of thirty images only the first two were shown. Sorry about the formatting. Not an expert. I think the loop shouldn't be placed there as a whole and the indentation has to do something with the bad results. Any tips will be highly appreciated.
Thanks
...code
from PIL import Image
import os, sys
path = 'C:\\Users\\Owner\\Desktop\\Images\\'
dirs = os.listdir( path )
....Code
if __name__ == '__main__':
...code
for item in dirs:
if os.path.isfile(path+item):
im = Image.open(path+item)
f, e = os.path.splitext(path+item)
loadedImage = path + item
parser.add_argument('--image', type=str, default='loadedImage')
....code
for i, single_3d in enumerate(pose_3d):
plot_pose(single_3d)
pass
I switched the above code to and it worked. However, my images are nor displayed sequentially. Can anyone tell me how to fix this?:
This is the code:
import argparse
import logging
import time
import os
import ast
import common
import cv2
import numpy as np
from estimator import TfPoseEstimator
from networks import get_graph_path, model_wh
import sys
from PIL import Image
path = 'C:\\Users\\Owner\\Desktop\\data\\'
dirs = os.listdir(path)
dirs.sort()
from lifting.prob_model import Prob3dPose
from lifting.draw import plot_pose
logger = logging.getLogger('TfPoseEstimator')
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('[%(asctime)s] [%(name)s] [%(levelname)s] %
(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
if __name__ == '__main__':
os.chdir('..')
for item in dirs:
im = Image.open(path+item)
f, e = os.path.splitext(path+item)
parser = argparse.ArgumentParser(description='tf-pose-estimation run')
nameimage = f + e
print(nameimage)
parser.add_argument('--image', type=str, default = nameimage)
parser.add_argument('--model', type=str,
default='mobilenet_thin_432x368', help='cmu_640x480 / cmu_640x360 /
mobilenet_thin_432x368')
parser.add_argument('--scales', type=str, default='[1.0, (1.1, 0.05)]', help='for multiple scales, eg. [1.0, (1.1, 0.05)]')
args = parser.parse_args()
scales = ast.literal_eval(args.scales)
w, h = model_wh(args.model)
e = TfPoseEstimator(get_graph_path(args.model), target_size=(w, h))
image = common.read_imgfile(args.image, None, None)
t = time.time()
humans = e.inference(image, scales=[None])
elapsed = time.time() - t
logger.info('inference image: %s in %.4f seconds.' % (args.image, elapsed))
image = cv2.imread(args.image, cv2.IMREAD_COLOR)
image = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
cv2.imshow('tf-pose-estimation result', image)
cv2.waitKey()
logger.info('3d lifting initialization.')
poseLifting = Prob3dPose('./src/lifting/models/prob_model_params.mat')
image_h, image_w = image.shape[:2]
standard_w = 640
standard_h = 480
pose_2d_mpiis = []
visibilities = []
for human in humans:
pose_2d_mpii, visibility = common.MPIIPart.from_coco(human)
pose_2d_mpiis.append([(int(x * standard_w + 0.5), int(y * standard_h + 0.5)) for x, y in pose_2d_mpii])
visibilities.append(visibility)
pose_2d_mpiis = np.array(pose_2d_mpiis)
visibilities = np.array(visibilities)
transformed_pose2d, weights = poseLifting.transform_joints(pose_2d_mpiis, visibilities)
pose_3d = poseLifting.compute_3d(transformed_pose2d, weights)
pose_3dqt = np.array(pose_3d[0]).transpose()
for point in pose_3dqt:
#my points print(point)
import matplotlib.pyplot as plt
fig = plt.figure()
a = fig.add_subplot(2, 2, 1)
a.set_title('Result')
plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
a = fig.add_subplot(2, 2, 2)
tmp = np.amax(e.heatMat, axis=2)
plt.imshow(tmp, cmap=plt.cm.gray, alpha=0.5)
plt.colorbar()
tmp2 = e.pafMat.transpose((2, 0, 1))
tmp2_odd = np.amax(np.absolute(tmp2[::2, :, :]), axis=0)
tmp2_even = np.amax(np.absolute(tmp2[1::2, :, :]), axis=0)
a = fig.add_subplot(2, 2, 3)
a.set_title('Vectormap-x')
plt.imshow(tmp2_odd, cmap=plt.cm.gray, alpha=0.5)
plt.colorbar()
a = fig.add_subplot(2, 2, 4)
a.set_title('Vectormap-y')
plt.imshow(tmp2_even, cmap=plt.cm.gray, alpha=0.5)
plt.colorbar()
for i, single_3d in enumerate(pose_3d):
plot_pose(single_3d)
plt.show()
pass
Image 1 Jumps to image 10.
The answer from this question may provide some example how to read the image in the folder.
My jpg pictures are stored sequentially pic0,pic1,pic2,pic3,pic4,pic20,pic30,pic100 but my code displays the images pic0,pic1,pic100,pic2,pic20,pic3,pic30.... How do I avoid that.?
The issue is with the way the name in the image dataset, and additionally with the sorting step you add after reading the directory list. My suggestion is to rename the file image to have zero leading (example pic000, pic001, .., pic010, pic011, ..).
To rename the files (given your image names), a minimal example:
import os
s1 = os.listdir('.')
for s in s1:
if ".jpg" not in s:
continue
if len(s)==8: # handle pic1.jpg pic2.jpg
#print(s[:-5] + '00' + s[3] + '.jpg')
os.rename(s, s[:-5] + '00' + s[3] + '.jpg')
elif len(s)==9: # handle pic10.jpg pic11.jpg
os.rename(s, s[:-6] + '0' + s[3:5] + '.jpg')

Python IOError: Too many open files, loading data and training CNN simultaneously

I am trying to debug a data preprocessor for training a CNN. (it tries to load data along with training). Giving out the too many open files error with a dataset of > 400 images (less than roughly 400 works). Here's the code. It's sort of like a mem leak going on, maybe too many files are being queued? Or I am not deleting something(PIL? But it closes files on its own).
def buffered_gen_mp(pil_img_gen, buffer_size=2):
"""
Generator that runs a slow source generator in a separate process.
buffer_size: the maximal number of items to pre-generate (length of the buffer)
"""
buffer = mp.Queue(maxsize=buffer_size-1)
def _buffered_generation_process(pil_img_gen_, buffer):
for (img_fname,img),(limg_fname,limg) in pil_img_gen_:
sio = StringIO.StringIO()
img.save(sio, 'PNG')
img_enc = sio.getvalue()
sio.close()
sio = StringIO.StringIO()
limg.save(sio, 'PNG')
limg_enc = sio.getvalue()
sio.close()
buffer.put(((img_fname,img_enc),(limg_fname,limg_enc)), block=True)
buffer.put(None) # sentinel: signal the end of the iterator
buffer.close()
process = mp.Process(target=_buffered_generation_process, args=(pil_img_gen, buffer))
process.start()
for data in iter(buffer.get, None):
(img_fname,img_enc),(limg_fname,limg_enc) = data
img = Image.open(StringIO.StringIO(img_enc))
limg = Image.open(StringIO.StringIO(limg_enc))
yield ((img_fname,img),(limg_fname,limg))
def ImageFnameGen(data_dir, img=True, label=True, depth=False, disp=False):
for inst_dir in sorted(data_dir.dirs()):
out = []
img_fname = inst_dir/'image.jpg'
limg_fname = inst_dir/'labels.png'
if img:
out.append(img_fname)
if label:
out.append(limg_fname)
yield out
def PilImageGen(img_fname_g):
for fnames in img_fname_g:
out = []
for fname in fnames:
out.append((fname,Image.open(str(fname))))
yield out
def ScaledImageGen(cfg, data_dir=None, randomize=True, loop=True):
img_fname_gen = ImageFnameGen(data_dir)
pil_img_gen = PilImageGen(img_fname_gen)
out = []
for (img_fname,img),(limg_fname,limg) in pil_img_gen:
# resize img and limg
out.append(((img_fname,img),(limg_fname,limg)))
while True:
if randomize:
random.shuffle(out)
for item in out:
yield item
if not loop:
break
def GeomJitImageGen(cfg, scaled_img_gen):
#stuff
while True:
for (img_fname, img), (limg_fname, limg) in scaled_img_gen:
# do some stuff
img = np.asarray(img).astype(np.double)
limg = np.asarray(limg).astype(np.double)
wimg = warper_x(img).clip(0,255).astype(np.uint8)
wlimg = warper_y(limg).clip(0,255).astype(np.uint8)
yield (img_fname, Image.fromarray(wimg)), (limg_fname, Image.fromarray(wlimg))
def PhotoJitImageGen(img_gen):
# define weights, algorithm
while True:
for (img_fname, img), (limg_fname, limg) in img_gen:
alg = np.random.choice(algorithms,p=weights)
jimg = alg(img)
yield (img_fname, jimg), (limg_fname, limg)
class Loader(object):
def __init__(self, args, expt):
# define self.cfg
input_gen = buffered_gen_mp(PhotoJitImageGen(GeomJitImageGen(self.cfg, ScaledImageGen(self.cfg))), buffer_size=32*8)
self.input_gen = input_gen
# stuff
def __call__(self, x_shared, y_shared):
assert(len(x_shared)==len(y_shared))
n = len(x_shared)
for ix in xrange(n):
(img_fname, pil_img), (limg_fname, pil_limg) = self.input_gen.next()
img = np.asarray(pil_img)
limg = np.asarray(pil_limg)
# stuff

Python OpenCV Error

Simple Code used to identify playing cards through a cam but I have Been trying to run this code but I keep getting this error when attempting to use any of the methods
TypeError: src is not a numpy array, neither a scalar
import sys
import numpy as np
sys.path.insert(0, "/usr/local/lib/python2.7/site-packages/")
import cv2
###############################################################################
# Utility code
###############################################################################
def rectify(h):
h = h.reshape((4,2))
hnew = np.zeros((4,2),dtype = np.float32)
add = h.sum(1)
hnew[0] = h[np.argmin(add)]
hnew[2] = h[np.argmax(add)]
diff = np.diff(h,axis = 1)
hnew[1] = h[np.argmin(diff)]
hnew[3] = h[np.argmax(diff)]
return hnew
###############################################################################
# Image Matching
###############################################################################
def preprocess(img):
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(5,5),2 )
thresh = cv2.adaptiveThreshold(blur,255,1,1,11,1)
return thresh
def imgdiff(img1,img2):
img1 = cv2.GaussianBlur(img1,(5,5),5)
img2 = cv2.GaussianBlur(img2,(5,5),5)
diff = cv2.absdiff(img1,img2)
diff = cv2.GaussianBlur(diff,(5,5),5)
flag, diff = cv2.threshold(diff, 200, 255, cv2.THRESH_BINARY)
return np.sum(diff)
def find_closest_card(training,img):
features = preprocess(img)
return sorted(training.values(), key=lambda x:imgdiff(x[1],features))[0][0]
###############################################################################
# Card Extraction
###############################################################################
def getCards(im, numcards=4):
gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray,(1,1),1000)
flag, thresh = cv2.threshold(blur, 120, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea,reverse=True)[:numcards]
for card in contours:
peri = cv2.arcLength(card,True)
approx = rectify(cv2.approxPolyDP(card,0.02*peri,True))
# box = np.int0(approx)
# cv2.drawContours(im,[box],0,(255,255,0),6)
# imx = cv2.resize(im,(1000,600))
# cv2.imshow('a',imx)
h = np.array([ [0,0],[449,0],[449,449],[0,449] ],np.float32)
transform = cv2.getPerspectiveTransform(approx,h)
warp = cv2.warpPerspective(im,transform,(450,450))
yield warp
def get_training(training_labels_filename,training_image_filename,num_training_cards,avoid_cards=None):
training = {}
labels = {}
for line in file(training_labels_filename):
key, num, suit = line.strip().split()
labels[int(key)] = (num,suit)
print "Training"
im = cv2.imread(training_image_filename)
for i,c in enumerate(getCards(im,num_training_cards)):
if avoid_cards is None or (labels[i][0] not in avoid_cards[0] and labels[i][1] not in avoid_cards[1]):
training[i] = (labels[i], preprocess(c))
print "Done training"
return training
if __name__ == '__main__':
if len(sys.argv) == 6:
filename = sys.argv[1]
num_cards = int(sys.argv[2])
training_image_filename = sys.argv[3]
training_labels_filename = sys.argv[4]
num_training_cards = int(sys.argv[5])
training = get_training(training_labels_filename,training_image_filename,num_training_cards)
im = cv2.imread("test")
width = im.shape[0]
height = im.shape[1]
if width < height:
im = cv2.transpose(im)
im = cv2.flip(im,1)
# Debug: uncomment to see registered images
#for i,c in enumerate(getCards(im,num_cards)):
# card = find_closest_card(training,c,)
# cv2.imshow(str(card),c)
# cv2.waitKey(0)
cards = [find_closest_card(training,c) for c in getCards(im,num_cards)]
print cards
else:
print __doc__
here is the entire error message
Traceback (most recent call last):
File "<pyshell#15>", line 1, in <module>
preprocess("test.JPG")
File "C:\Users\Don Ellison\Desktop\Class Programs\CSC 490 Project\Cards\Python\Playing-Card-Recognition-master\card_img.py", line 43, in preprocess
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
TypeError: src is not a numpy array, neither a scalar
you are passing in wrong argument to preprocess function, I guess you are calling it from a python shell.
You are not suppose to pass in a image file name, but rather a numpy array. It seems you called proprocess function and passed in "test.JPG" in your python shell. If you want to test your preprocess function, do
test_img = cv2.imread("test.JPG")
preprocess(test_img)

Categories