From 3ac2df22a157b4149a0f1512382cba99d367f4bc Mon Sep 17 00:00:00 2001
From: xdu12 <xdu12@illinois.edu>
Date: Mon, 20 Nov 2017 20:44:14 -0600
Subject: [PATCH] Initial commit

---
 hicopy.py | 672 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 672 insertions(+)
 create mode 100644 hicopy.py

diff --git a/hicopy.py b/hicopy.py
new file mode 100644
index 0000000..f7ddfa0
--- /dev/null
+++ b/hicopy.py
@@ -0,0 +1,672 @@
+# -*- coding: utf-8 -*-
+"""
+Created on Sat Sep 30 23:36:15 2017
+
+@author: Xiaodan Du
+"""
+__author__ = 'Xiaodan Du'
+__version__ = '1.0'
+
+import json
+from PIL import Image
+from PIL import ImageFont
+from PIL import ImageDraw 
+from pprint import pprint
+import fileinput
+import time
+import matplotlib.pyplot as plt
+import matplotlib.patches as patches
+import matplotlib.image as mpimg
+from matplotlib import rcParams
+from matplotlib.lines import Line2D
+from matplotlib.collections import PatchCollection
+import numpy as np
+import copy
+import itertools
+#from . import mask as maskUtils
+import os
+from collections import defaultdict
+import sys
+'''
+This is a function to read the JSON file of HICO-DET dataset
+index/id of image and cat(hoi) starts from 1 instead of 0
+index/ids must be integer and must be within the total number
+Default location of the JSON file:'C:\\Users\\du_xi\\Dropbox\\Research Shuai Tang\\list.json'
+Default location of the images:'C:\\Users\\du_xi\\.spyder-py3\\hico_20160224_det'
+
+Functions:
+    
+    test_dim: returns the dimension of the input list
+    
+    hicopy Class:
+        -checkMultiHoi: checks if an image has multiple hois
+        -createIndex: a helper function of the constructor to create the class variables
+        -getAllNname: returns a list of all object names
+        -getAllVname: returns a list of all verb names
+        -getCatIds: gets the hoi ids that contains given verbs and objects
+        -getHoiIds: returns the ids that contain certain verbs and objects
+        -getHoiIdsBasedOnVname: returns a list of all hoi ids that contain the given verb name
+        -getHoiIdsBasedOnNname: returns a list of all hoi ids that contain the given objective name
+        -getHoiNames: returns a list of hoi ids given image ids
+        -getHoiNum: returns the total number of hois
+        -getImgHoi: returns a list of hoi ids and a list of how many humans in each hoi of a given image id   
+        -getImgId: a helper function of getImgIds
+        -getImgIds: given a list of image ids and a list of hoi ids, returns a list of the ids of the images that belong to the given hois
+        -getNnames: returns the names of given object ids 
+        -getNnameIds: returns the ids of given object names
+        -getNumOfNoInteraction: returns the number of "no_interaction" humans of a given image id
+        -getObjectNum: returns the total number of objects
+        -getVerbNum: returns the total number of verbs
+        -getVnameIds: returns the ids of given verb names
+        -getVnames: returns the names of given verb ids       
+        -hicopy: Object that contains all information of the given JSON file      
+        -loadCats: returns a list of strings in the form of "verb object" with given hoi ids
+        -loadImgs: returns a list of images required
+        -readImgs: returns a list of images required (images are in np array format)
+        -visualize: visualize the bounding boxes and human-object interaction of a specific image
+        -visualize_box_conn_one: a helper function of visualize to create bounding boxes and lines
+'''
+def test_dim(testlist, dim=0):
+       """
+       This is a function from the internect:"https://stackoverflow.com/questions/15985389/python-check-if-list-is-multidimensional-or-one-dimensional"
+       tests if testlist is a list and how many dimensions it has
+       returns -1 if it is no list at all, 0 if list is empty 
+       and otherwise the dimensions of it
+       """
+       if isinstance(testlist, list):
+          if testlist == []:
+              return dim
+          dim = dim + 1
+          dim = test_dim(testlist[0], dim)
+          return dim
+       else:
+          if dim == 0:
+              return -1
+          else:
+              return dim
+          
+class hicopy:
+    def __init__(self, annotation_file='C:\\Users\\du_xi\\Dropbox\\Research Shuai Tang\\list.json'):
+        """
+        The constructor of hicopy class
+        input: 
+            annotation_file: the location of the JSON file that contains all information. Default location only works for me. Please
+                            change it to where you put the JSON file.
+        """
+        self.dataset=dict()
+        self.anno_test=np.empty
+        self.anno_train=np.empty
+        self.bbox_test=list()
+        self.bbox_train=list()
+        self.list_action=list()
+        self.list_test=list()
+        self.list_train=list()
+        if not annotation_file == None:
+            print('loading annotations into memory...')
+            tic = time.time()
+            dataset = json.load(open(annotation_file, 'r'))
+            assert type(dataset)==dict, 'annotation file format {} not supported'.format(type(dataset))
+            print('Done (t={:0.2f}s)'.format(time.time()- tic))
+            self.dataset = dataset
+            self.createIndex()
+            
+
+    def createIndex(self):
+        """
+        This function creates the seven class members of hicopy objects
+        """
+        # create index
+        print('creating index...')
+        anno_test=np.empty
+        anno_train=np.empty
+        bbox_test=list()
+        bbox_train=list()
+        list_action=list()
+        list_test=list()
+        list_train=list()
+        if 'anno_test' in self.dataset:
+            anno_test_list = self.dataset['anno_test']
+            anno_test_list = [[x if x !='null' else np.nan for x in y] for y in anno_test_list]
+            anno_test=np.array(anno_test_list)
+        if 'anno_train' in self.dataset:
+            anno_train_list = self.dataset['anno_train']
+            anno_train_list = [[x if x !='null' else np.nan for x in y] for y in anno_train_list]
+            anno_train=np.array(anno_train_list)
+        if 'list_test' in self.dataset:
+            list_test = self.dataset['list_test']
+        if 'list_train' in self.dataset:
+            list_train = self.dataset['list_train']
+        if 'bbox_test' in self.dataset:
+            bbox_test = self.dataset['bbox_test']
+        if 'bbox_train' in self.dataset:
+            bbox_train = self.dataset['bbox_train']
+        if 'list_action' in self.dataset:
+            list_action = self.dataset['list_action']
+        print('index created!')
+
+        # create class members
+        self.anno_test = anno_test
+        self.anno_train = anno_train
+        self.list_test = list_test
+        self.list_train = list_train
+        self.bbox_test = bbox_test
+        self.bbox_train = bbox_train
+        self.list_action = list_action
+        
+    def getImgIds(self, imgIds=[], catIds=[]):
+        """
+        inputs:
+            imgIds: a list of image ids
+            catIds: a list of hoi ids
+        outputs:
+            list(ids): a list of image ids that contain given hois
+        Note: If imgIds is empty, function will use all image ids as imgIds
+              If catIds is empty, fucntion will use all hoi ids as catIds
+              In case both imgIds and catIds are empty, function will return all hoi ids
+        """
+#        ids=list()
+#        if dataType=='imgIds':
+#            
+#            for i in index:
+#                ids.append(self.list_train[i])
+#        elif dataYpe=='hoiIds':
+#            for i in index:
+        if len(imgIds) == len(catIds) == 0:
+            ids = self.list_train
+        else:
+            ids = set(imgIds)
+            for i, catId in enumerate(catIds):
+                if i == 0 and len(ids) == 0:
+                    ids = set(self.getImgId(catId,imgIds))
+                else:
+                    ids &= set(self.getImgId(catId,imgIds))
+        return list(ids)
+    def getImgId(self, catId,imgIds=[]):
+        """
+        inputs:
+            catId: integer, id of hoi
+            imgIds: a list of image ids
+        outputs:
+            ids: a list of image ids that contain the given hoi
+        Note: If imgIds is empty, function will use all image ids as imgIds
+        """
+        ids=list()
+        if len(imgIds)==0:
+            for i in range(len(self.bbox_train)):
+                hoiNum=self.checkMultiHoi('bbox_train',i)
+                if hoiNum==0:
+                    if self.bbox_train[i]['hoi']['id']==catId:
+                        ids.append(i+1)
+                else:
+                    for j in range(hoiNum):
+                        if self.bbox_train[i]['hoi'][j]['id']==catId:
+                            ids.append(i+1)
+                            break
+        else:
+            for i in imgIds:
+                hoiNum=self.checkMultiHoi('bbox_train',i-1)
+                if hoiNum==0:
+                    if self.bbox_train[i-1]['hoi']['id']==catId:
+                        ids.append(i)
+                else:
+                    for j in range(hoiNum):
+                        if self.bbox_train[i-1]['hoi'][j]['id']==catId:
+                            ids.append(i)
+                            break
+        return ids
+                
+    def checkMultiHoi(self,key,i):
+        """
+        inputs: 
+            key: either 'bbox_train' or 'bbox_test'
+            i: the index of an image in bbox_train or bbox_test. Note: i starts from 0, so if you have 
+                the index of a certain image, i should be index-1
+        outputs:
+            0: if the image has only 1 hoi
+            an integer n: if the image has n hois
+            nothing: if key is incorrect
+        """
+        if key=='bbox_train':
+            if isinstance(self.bbox_train[i]['hoi'],dict):
+                return 0
+            else:
+                return len(self.bbox_train[i]['hoi'])
+        elif key=='bbox_test':
+            if isinstance(self.bbox_test[i]['hoi'],dict):
+                return 0
+            else:
+                return len(self.bbox_test[i]['hoi'])
+        else:
+            print('Wrong Type of "key". "bbox_train" or "bbox_test" only!')
+            return
+            
+    def loadImgs(self, ids=[],hicolocation='C:\\Users\\du_xi\\.spyder-py3\\hico_20160224_det'):
+        """
+        inputs:
+            ids: a list of image ids that are to be loaded
+            hicolocation: the location of all the images. Default location only works for my computer. Please change.
+        outputs:
+            imgs: a list of images
+        Note: ids cannot be empty.
+              This function uses Image.open() to load images. If you want a 3D np array, please chceck readImgs() in this class.
+        """
+        imgs=list()
+        for i in ids:
+            fileName=self.list_train[i-1]
+            im_file=hicolocation+'\\images\\train2015\\'+fileName
+            img = Image.open(im_file)
+            imgs.append(img)
+            #img.show()
+        return imgs
+    
+    def readImgs(self,ids=[],hicolocation='C:\\Users\\du_xi\\.spyder-py3\\hico_20160224_det'):
+        """
+        inputs: 
+            ids: a list of image ids that are to be loaded
+            hicolocation: the location of all the images. Default location only works for my computer. Please change.
+        outputs:
+            imgs: a list of images (in np array format)
+        Note:
+            Dimension of the np array: (height,width,R-G-B)
+        """
+        imgs=list()
+        for i in ids:
+            fileName=self.list_train[i-1]
+            im_file=hicolocation+'\\images\\train2015\\'+fileName
+            img = mpimg.imread(im_file)
+            imgs.append(img)
+            #img.show()
+        return imgs
+    
+    def getCatIds(self, catVNms=[],catNNms=[]):
+        """
+        inputs:
+            catVNms: a list of string of verb names
+            catNNms: a list of string of object names
+        outputs:
+            sorted(list(cats)): a sorted list of hoi ids that satisfy both given verbs and objects
+        Note:
+            If catVNms is empty, the function will use all verbs as catVNms
+            If catNNms is empty, the function will use all objects as catNNms
+            In case both inputs are empty, the function will directly return a list of all hoi ids
+        """
+        if len(catVNms) == len(catNNms) == 0:
+            cats = list(range(1,len(self.list_action)+1))
+        else:
+            cats = list(range(1,len(self.list_action)+1))
+            catsV = cats if len(catVNms) == 0 else [cat for cat in cats if self.list_action[cat-1]['vname']          in catVNms]
+            catsN = cats if len(catNNms) == 0 else [cat for cat in cats if self.list_action[cat-1]['nname']          in catNNms]
+            catsV=set(catsV)
+            catsN=set(catsN)
+            cats=catsV&catsN
+        return sorted(list(cats))
+    
+    def loadCats(self, ids=[]):
+        """
+        Load cats with the specified ids.
+        :param ids (int list)       : integer ids specifying hois
+        :return: cats (string list) : "verb"+" "+"object"
+        Note:
+            If ids is empty, the function returns nothing.
+        """
+        if len(ids)==0:
+            return
+        else:
+            hoi=list()
+            for i in ids:
+                hoi.append(self.list_action[i-1]['vname']+' '+self.list_action[i-1]['nname'])
+            return hoi
+        
+    def getHoiNames(self, ids=[]):
+        """
+        inputs:
+            ids: a list of hoi ids
+        outputs:
+            hoiIds: a list of string of names of given hoi ids
+        Note:
+            If ids is empty, the function will return nothing
+            Elements in ids must be valid ids (integers larger than 0 and smaller or equal to 600)
+        """
+        if len(ids)==0:
+            return
+        else:
+            hoiIds=list()
+            for i in ids:
+                hoiNum=self.checkMultiHoi('bbox_train',i-1)
+                if hoiNum==0:
+                    hoiIds.append(self.bbox_train[i-1]['hoi']['id'])
+                else:
+                    hoiIds.append([self.bbox_train[i-1]['hoi'][j]['id'] for j in range(hoiNum)])
+            return hoiIds        
+                                    
+    def visualize(self,imageIndex,hoiIndex=[],hicolocation='C:\\Users\\du_xi\\.spyder-py3\\hico_20160224_det'):
+        """
+        inputs: 
+            imageIndex: a list of an integer of image id
+            hoiIndex: a list or an integer of hoi id
+            hicolocation: the location of all the images. Default location only works for my computer. Please change.
+        outputs: 
+            visualization of annotations
+        """
+        if isinstance(imageIndex,list) and len(imageIndex)==0:
+            return
+        if isinstance(hoiIndex,int) and hoiIndex>0 and hoiIndex<=600:
+            for i in imageIndex:
+                fileName=self.bbox_train[i-1]['filename']
+                im_file=hicolocation+'\\images\\train2015\\'+fileName
+                
+                if isinstance(self.bbox_train[i-1]['hoi'],dict):
+                    hoi_invis=self.bbox_train[i-1]['hoi']['invis']
+                    if self.bbox_train[i-1]['hoi']['id']==hoiIndex:
+                        hoi_id = hoiIndex
+                    else:
+                        print('Image does not have such hoi.')
+                        return
+                    bboxhuman=self.bbox_train[i-1]['hoi']['bboxhuman']
+                    bboxobject=self.bbox_train[i-1]['hoi']['bboxobject']
+                    connection=self.bbox_train[i-1]['hoi']['connection']
+                else:
+                    imageHois=list()
+                    for j, hoiId in enumerate(self.bbox_train[i-1]['hoi']):
+                        imageHois.append(hoiId['id'])
+                    if hoiIndex in imageHois:
+                        k = imageHois.index(hoiIndex)
+                        hoi_invis=self.bbox_train[i-1]['hoi'][k]['invis'] 
+                        hoi_id = self.bbox_train[i-1]['hoi'][k]['id']
+                        bboxhuman=self.bbox_train[i-1]['hoi'][k]['bboxhuman']
+                        bboxobject=self.bbox_train[i-1]['hoi'][k]['bboxobject']
+                        connection=self.bbox_train[i-1]['hoi'][k]['connection']
+                    else:
+                        print('Image does not have such hoi.')
+                        return
+                aname = self.list_action[hoi_id]['vname_ing']+' '+self.list_action[hoi_id]['nname']
+                img=mpimg.imread(im_file)
+                fig,ax = plt.subplots(1)
+                imgplot = plt.imshow(img)
+                plt.axis('off')
+                plt.title(aname,fontSize=48,color='black')              
+                print(self.bbox_train[i-1])
+                if hoi_invis:
+                    print('hoi not visible\n')
+                else:
+                    self.visualize_box_conn_one(ax,bboxhuman, bboxobject, connection, 'b','g','r')
+                rcParams['figure.figsize'] = [20, 20]
+                plt.show()
+        else:
+            for i in imageIndex:
+                fileName=self.bbox_train[i-1]['filename']
+                im_file=hicolocation+'\\images\\train2015\\'+fileName
+                img = Image.open(im_file)
+                img.show()
+        
+    def visualize_box_conn_one(self, ax,bboxhuman, bboxobject, connection, color1='b',color2='g',color3='r'):
+        if isinstance(bboxhuman,list):
+            for r in range(len(bboxhuman)):
+                rt = [bboxhuman[r]['x1'], bboxhuman[r]['y1'], bboxhuman[r]['x2']-bboxhuman[r]['x1']+1, bboxhuman[r]['y2']-bboxhuman[r]['y1']+1]
+                rect = patches.Rectangle((rt[0],rt[1]),rt[2],rt[3],linewidth=4,edgecolor=color1,facecolor='none')
+                ax.add_patch(rect)
+        else:
+            rt = [bboxhuman['x1'], bboxhuman['y1'], bboxhuman['x2']-bboxhuman['x1']+1, bboxhuman['y2']-bboxhuman['y1']+1]
+            rect=patches.Rectangle((rt[0],rt[1]),rt[2],rt[3],linewidth=4,edgecolor=color1,facecolor='none')
+            ax.add_patch(rect)
+        if isinstance(bboxobject,list):
+            for r in range(len(bboxobject)):
+                rt = [bboxobject[r]['x1'], bboxobject[r]['y1'], bboxobject[r]['x2']-bboxobject[r]['x1']+1, bboxobject[r]['y2']-bboxobject[r]['y1']+1]
+                rect2 = patches.Rectangle((rt[0],rt[1]),rt[2],rt[3],linewidth=4,edgecolor=color2,facecolor='none')
+                ax.add_patch(rect2)
+        else:
+            rt = [bboxobject['x1'], bboxobject['y1'], bboxobject['x2']-bboxobject['x1']+1, bboxobject['y2']-bboxobject['y1']+1]
+            rect2=patches.Rectangle((rt[0],rt[1]),rt[2],rt[3],linewidth=4,edgecolor=color2,facecolor='none')
+            ax.add_patch(rect2)    
+        if test_dim(connection)==1:
+            rt1=bboxhuman
+            rt2=bboxobject
+            ct1 = [(rt1['x1']+rt1['x2'])/2, (rt1['y1']+rt1['y2'])/2]
+            ct2 = [(rt2['x1']+rt2['x2'])/2, (rt2['y1']+rt2['y2'])/2]
+            markers_on = [0, -1]
+            line = Line2D([ct1[0],ct2[0]],[ct1[1],ct2[1]],linewidth=4,color=color3,markevery=markers_on,marker='o',markersize=10,markerfacecolor=color3)
+            ax.add_line(line)
+        else:
+            for r in range(len(connection)):
+                rt1=bboxhuman[connection[r][0]-1]
+                rt2=bboxobject[connection[r][1]-1]
+                ct1 = [(rt1['x1']+rt1['x2'])/2, (rt1['y1']+rt1['y2'])/2]
+                ct2 = [(rt2['x1']+rt2['x2'])/2, (rt2['y1']+rt2['y2'])/2]
+                markers_on = [0, -1]
+                line = Line2D([ct1[0],ct2[0]],[ct1[1],ct2[1]],linewidth=4,color=color3,markevery=markers_on,marker='o',markersize=10,markerfacecolor=color3)
+                ax.add_line(line)
+            
+    def getAllNname(self):
+        allNname=list()
+        for i in range(len(self.list_action)):
+            if self.list_action[i]['nname'] not in allNname:
+                allNname.append(self.list_action[i]['nname'])
+        return sorted(allNname)
+    
+    def getAllVname(self):
+        allVname=list()
+        for i in range(len(self.list_action)):
+            if self.list_action[i]['vname'] not in allVname:
+                allVname.append(self.list_action[i]['vname'])
+        return sorted(allVname)        
+    
+    def getNnames(self,index):
+        """
+        inputs:
+            index: a list or an integer of object ids
+        outputs:
+            a list of names of given objects
+        Note: 
+            If index is empty, the function will return all object names
+        """
+        allNname=self.getAllNname()
+        if index==[]:
+            return allNname
+        return [allNname[i-1] for i in index] if isinstance(index,list) else allNname[index-1]
+    
+    def getVnames(self,index):
+        """
+        inputs:
+            index: a list or an integer of verb ids
+        outputs:
+            a list of names of given verbs
+        Note: 
+            If index is empty, the function will return all verb names
+        """
+        allVname=self.getAllVname()
+        if index==[]:
+            return allVname
+        return [allVname[i-1] for i in index] if isinstance(index,list) else allVname[index-1]
+    
+    def getNnameIds(self,nname):
+        """
+        inputs:
+            nname: a list or an integer of object ids
+        outputs:
+            a list of ids of given object names
+        Note:
+            If nname is empty, the function will return a list of all object ids
+        """
+        allNname=self.getAllNname()
+        if nname==[]:
+            return sorted(range(1,self.getObjectNum()+1))
+        return [allNname.index(i)+1 for i in nname] if isinstance(nname,list) else allNname.index(nname)+1
+    
+    def getVnameIds(self,vname):
+        """
+        inputs:
+            vname: a list or an integer of verb ids
+        outputs:
+            a list of ids of given verb names
+        Note:
+            If vname is empty, the function will return a list of all verb ids
+        """
+        allVname=self.getAllVname()
+        if vname==[]:
+            return sorted(range(1,self.getVerbNum()+1))
+        return [allVname.index(i)+1 for i in vname] if isinstance(vname,list) else allVname.index(vname)+1
+    
+    def getVerbNum(self):
+        """
+        outputs:
+            an integer of the total types of verbs
+        """
+        return len(self.getAllVname())
+    
+    def getObjectNum(self):
+        """
+        outputs:
+            an integer of the total types of objectives
+        """
+        return len(self.getAllNname())
+    
+    def getHoiNum(self):
+        """
+        outputs:
+            an integer of the total types of hois
+        """
+        return len(self.list_action)
+        
+    def getHoiIds(self,**vn):
+        """
+        inputs:
+            **vn: input keys can only be "vname" or "nname". 
+                  "vname": a list of strings of verb names
+                  "nname": a list of strings of object names
+        outputs:
+            sorted(HoiIds): a sorted list of hoi ids
+        """
+        if any(key=='vname' or 'nname' for key in vn)==0:
+            return sorted(range(1,self.getHoiNum()+1))
+        if all(key=='vname' or 'nname' for key in vn)==0:
+            print('Inputs can only be "vname" or "nname"!')
+            return
+        if 'vname' in vn:
+            vHoiIds=set(self.getHoiIdsBasedOnVname(vn['vname']))
+        else:
+            vHoiIds=set(range(1,self.getHoiNum()+1))
+        if 'nname' in vn:
+            nHoiIds=set(self.getHoiIdsBasedOnNname(vn['nname']))
+        else:
+            nHoiIds=set(range(1,self.getHoiNum()+1))
+        HoiIds=vHoiIds&nHoiIds
+        return sorted(HoiIds)
+            
+    def getHoiIdsBasedOnVname(self,vname):
+        """
+        inputs:
+            vname: a list of verb names
+        outputs:
+            sorted(HoiIds): a sorted list of hoi ids
+        """
+        HoiIds=list()
+        if vname==[]:
+            vname = self.getVnameIds(vname)
+        if isinstance(vname,list):
+            for i in range(self.getHoiNum()):            
+                if self.list_action[i]['vname'] in self.getVnames(vname):
+                    HoiIds.append(i+1)
+        else:
+            for i in range(self.getHoiNum()):
+                if self.list_action[i]['vname'] == self.getVnames(vname):
+                    HoiIds.append(i+1)
+        return sorted(HoiIds)
+    
+    def getHoiIdsBasedOnNname(self,nname):
+        """
+        inputs:
+            nname: a list of object names
+        outputs:
+            sorted(HoiIds): a sorted list of hoi ids
+        """
+        HoiIds=list()
+        if nname==[]:
+            nname = self.getNnameIds(nname)
+        if isinstance(nname,list):
+            for i in range(self.getHoiNum()):            
+                if self.list_action[i]['nname'] in self.getNnames(nname):
+                    HoiIds.append(i+1)
+        else:
+            for i in range(self.getHoiNum()):
+                if self.list_action[i]['nname'] == self.getNnames(nname):
+                    HoiIds.append(i+1)
+        return sorted(HoiIds)
+    
+    def getNnameIdsBasedOnHoiId(self,hoiId):
+        """
+        inputs: 
+            hoiId: an integer of hoi id
+        outputs:
+            nnameId: an integer of the id of the object in the given hoi
+        """
+        nname=self.list_action[hoiId-1]['nname']
+        nnameId=self.getNnameIds(nname)
+        return nnameId
+    
+    def getVnameIdsBasedOnHoiId(self,hoiId):
+        """
+        inputs: 
+            hoiId: an integer of hoi id
+        outputs:
+            vnameId: an integer of the id of the verb in the given hoi
+        """
+        vname=self.list_action[hoiId-1]['vname']
+        vnameId=self.getVnameIds(vname)
+        return vnameId
+    
+    def getImgHoi(self,index):
+        """
+        inputs: 
+            index: an integer of the id of an image
+        outputs:
+            imgHoi: an integer of the hoi id of the given image
+            personNum: the number of humans in the image
+        """
+        imgHoi=list()
+        personNum=list()
+        if isinstance(self.bbox_train[index-1]['hoi'],list):
+            for currHoi in self.bbox_train[index-1]['hoi']:
+                imgHoi.append(currHoi['id'])
+                if isinstance(currHoi['bboxhuman'],dict):
+                    personNum.append(1)
+                elif isinstance(currHoi['bboxhuman'],list):
+                    personNum.append(len(currHoi['bboxhuman']))
+                else:
+                    personNum.append(0)
+        elif isinstance(self.bbox_train[index-1]['hoi'],dict):
+            imgHoi.append(self.bbox_train[index-1]['hoi']['id'])
+            if isinstance(self.bbox_train[index-1]['hoi']['bboxhuman'],dict):
+                personNum.append(1)
+            elif isinstance(self.bbox_train[index-1]['hoi']['bboxhuman'],list):
+                personNum.append(len(self.bbox_train[index-1]['hoi']['bboxhuman']))
+            else:
+                personNum.append(0)
+        return imgHoi,personNum
+    
+    def getNumOfNoInteraction(self,index):
+        """
+        inputs:
+            index: an integer of the id of an image
+        outputs:
+            noInteraction: the number of "no_interaction" in a given image
+        """
+        imgHoi,personNum=self.getImgHoi(index)
+        noInteraction=0
+        noInteractionId=self.getVnameIds(['no_interaction'])[0]
+        for i,hoi in enumerate(imgHoi):
+            if self.getVnameIdsBasedOnHoiId(hoi)==noInteractionId:
+                noInteraction=noInteraction+personNum[i]
+        return noInteraction
+                
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
\ No newline at end of file
-- 
GitLab