playing-card-detection
playing-card-detection copied to clipboard
Transform just 1 card without hull and enclose entire card in bounding box and generate new scene
Hi, i was wondering that i wanted to generate a scene with just the card, without the hulls and my bounding box encloses the card. I have been trying to modify your code to do this but always run into errors. Could you take a look and advise what i am doing wrong. My code is:
`
# Scenario with 1 card:
# The original image of a cover has the shape (cardH,cardW,4)
# We first paste it in a zero image of shape (imgH,imgW,4) at position decalX, decalY
# so that the original image is centerd in the zero image
decalX=int((imgW-cardW)/2)
decalY=int((imgH-cardH)/2)
# imgaug keypoints of the bounding box of a whole card
def card_to_kps(decalX=decalX, decalY=decalY):
kps = ia.KeypointsOnImage([ia.Keypoint(x=decalX,y=decalY),
ia.Keypoint(x=decalX+length,y=decalY),
ia.Keypoint(x=decalX+length,y=decalY+breadth),
ia.Keypoint(x=decalX,y=decalY+breadth)], shape=(imgH,imgW,3))
return kps
def kps_to_polygon(kps):
#Convert imgaug keypoints to shapely polygon
pts=[(kp.x,kp.y) for kp in kps]
return Polygon(pts)
def kps_to_BB(kps):
"""
Determine imgaug bounding box from imgaug keypoints
"""
extend=3 # To make the bounding box a little bit bigger
kpsx=[kp.x for kp in kps.keypoints]
minx=max(0,int(min(kpsx)-extend))
maxx=min(imgW,int(max(kpsx)+extend))
kpsy=[kp.y for kp in kps.keypoints]
miny=max(0,int(min(kpsy)-extend))
maxy=min(imgH,int(max(kpsy)+extend))
if minx==maxx or miny==maxy:
return None
else:
return ia.BoundingBox(x1=minx,y1=miny,x2=maxx,y2=maxy
# imgaug transformation for card
transform_1card = iaa.Sequential([
iaa.Affine(scale=[0.65,1]),
iaa.Affine(rotate=(-180,180)),
iaa.Affine(translate_percent={"x":(-0.25,0.25),"y":(-0.25,0.25)}),
])
# imgaug transformation for the background
scaleBg=iaa.Resize({"height": imgH, "width": imgW})
def augment(img,list_kps,seq, restart=True):
"""
Apply augmentation 'seq' to image 'img' and keypoints 'list_kps'
If restart is False, the augmentation has been made deterministic outside the function
"""
# Make sequence deterministic
while True:
if restart:
myseq=seq.to_deterministic()
else:
myseq=seq
# Augment image, keypoints and bbs
img_aug = myseq.augment_images([img])[0]
list_kps_aug = [myseq.augment_keypoints([kp])[0] for kp in list_kps]
list_bbs = [kps_to_BB(list_kps_aug[1]),kps_to_BB(list_kps_aug[2])]
valid=True
# Check the cover bounding box stays inside the image
for bb in list_bbs:
if bb is None or int(round(bb.x2)) >= imgW or int(round(bb.y2)) >= imgH or int(bb.x1)<=0 or int(bb.y1)<=0:
valid=False
break
if valid: break
elif not restart:
img_aug=None
break
return img_aug,list_kps_aug,list_bbs
class BBA: # Bounding box + annotations
def __init__(self,bb,classname):
self.x1=int(round(bb.x1))
self.y1=int(round(bb.y1))
self.x2=int(round(bb.x2))
self.y2=int(round(bb.y2))
self.classname=card
class Scene:
def __init__(self,bg,img1):
self.createCardsScene(bg,img1)
def createCardsScene(self,bg,img1):
# Randomly transform 1st card
self.img1=np.zeros((imgH,imgW,4),dtype=np.uint8)
self.img1[decalY:decalY+cardH,decalX:decalX+cardW,:]=img1
self.img1, self.bbs1=augment(self.img1, transform_1cover)
#self.class1=class1
def display(self):
fig,ax=plt.subplots(1,figsize=(8,8))
ax.imshow(self.final)
for bb in self.listbba:
rect=patches.Rectangle((bb.x1,bb.y1),bb.x2-bb.x1,bb.y2-bb.y1,linewidth=1,edgecolor='b',facecolor='none')
ax.add_patch(rect)
def res(self):
return self.final
def write_files(self,save_dir,display=False):
jpg_fn, xml_fn=give_me_filename(save_dir, ["jpg","xml"])
plt.imsave(jpg_fn,self.final)
if display: print("New image saved in",jpg_fn)
create_voc_xml(xml_fn,jpg_fn, self.listbba,display=display)`
Hi, I imagine you get syntax errors, no ? Your code is not indented correctly (for instance the class Scene), or have missing parenthese (in return of the function kps_to_BB).
Hi , thanks for the reply. The indentations are not an issue and also the missing parentheses. Those are errors while pasting the code here. The issue i have is in how to randomly transform a card and paste it in a new background in the line,
self.img1, self.bbs1=augment(self.img1, transform_1cover)
i get errors like"missing one argument:seq" or "something like KeypointsOnImage is not iterable" when i try to pass kps as an argument, or even errors like 'list' object has no attribute 'keypoints' in the function def kps_to_bb(kps) I was wondering how to change the code such that i paste the entire card and the 4 corners as keypoints and transform them is such a way that it also returns bounding box coordinates of entire card
The error "missing one argument" seems very clear. You give only 2 arguments in the call to augment, while you should give 3 (missing argument: list_kps).
yes i understood that. i tried it and it gives me the above mentioned errors. i will try to solve myself in the meantime, but if you have any suggestions, it would be very helpful