[docs]defresize_short(src,size,interp=2):"""Resizes shorter edge to size. .. note:: `resize_short` uses OpenCV (not the CV2 Python library). MXNet must have been built with OpenCV for `resize_short` to work. Resizes the original image by setting the shorter edge to size and setting the longer edge accordingly. Resizing function is called from OpenCV. Parameters ---------- src : NDArray The original image. size : int The length to be set for the shorter edge. interp : int, optional, default=2 Interpolation method used for resizing the image. Possible values: 0: Nearest Neighbors Interpolation. 1: Bilinear interpolation. 2: Area-based (resampling using pixel area relation). It may be a preferred method for image decimation, as it gives moire-free results. But when the image is zoomed, it is similar to the Nearest Neighbors method. (used by default). 3: Bicubic interpolation over 4x4 pixel neighborhood. 4: Lanczos interpolation over 8x8 pixel neighborhood. 9: Cubic for enlarge, area for shrink, bilinear for others 10: Random select from interpolation method metioned above. Note: When shrinking an image, it will generally look best with AREA-based interpolation, whereas, when enlarging an image, it will generally look best with Bicubic (slow) or Bilinear (faster but still looks OK). More details can be found in the documentation of OpenCV, please refer to http://docs.opencv.org/master/da/d54/group__imgproc__transform.html. Returns ------- NDArray An 'NDArray' containing the resized image. Example ------- >>> with open("flower.jpeg", 'rb') as fp: ... str_image = fp.read() ... >>> image = mx.img.imdecode(str_image) >>> image <NDArray 2321x3482x3 @cpu(0)> >>> size = 640 >>> new_image = mx.img.resize_short(image, size) >>> new_image <NDArray 2321x3482x3 @cpu(0)> """h,w,_=src.shapeifh>w:new_h,new_w=size*h//w,sizeelse:new_h,new_w=size,size*w//hreturnimresize(src,new_w,new_h,interp=_get_interp_method(interp,(h,w,new_h,new_w)))

[docs]deffixed_crop(src,x0,y0,w,h,size=None,interp=2):"""Crop src at fixed location, and (optionally) resize it to size. Parameters ---------- src : NDArray Input image x0 : int Left boundary of the cropping area y0 : int Top boundary of the cropping area w : int Width of the cropping area h : int Height of the cropping area size : tuple of (w, h) Optional, resize to new size after cropping interp : int, optional, default=2 Interpolation method. See resize_short for details. Returns ------- NDArray An `NDArray` containing the cropped image. """out=nd.crop(src,begin=(y0,x0,0),end=(y0+h,x0+w,int(src.shape[2])))ifsizeisnotNoneand(w,h)!=size:sizes=(h,w,size[1],size[0])out=imresize(out,*size,interp=_get_interp_method(interp,sizes))returnout

[docs]defrandom_size_crop(src,size,area,ratio,interp=2,**kwargs):"""Randomly crop src with size. Randomize area and aspect ratio. Parameters ---------- src : NDArray Input image size : tuple of (int, int) Size of the crop formatted as (width, height). area : float in (0, 1] or tuple of (float, float) If tuple, minimum area and maximum area to be maintained after cropping If float, minimum area to be maintained after cropping, maximum area is set to 1.0 ratio : tuple of (float, float) Aspect ratio range as (min_aspect_ratio, max_aspect_ratio) interp: int, optional, default=2 Interpolation method. See resize_short for details. Returns ------- NDArray An `NDArray` containing the cropped image. Tuple A tuple (x, y, width, height) where (x, y) is top-left position of the crop in the original image and (width, height) are the dimensions of the cropped image. """h,w,_=src.shapesrc_area=h*wif'min_area'inkwargs:warnings.warn('`min_area` is deprecated. Please use `area` instead.',DeprecationWarning)area=kwargs.pop('min_area')assertnotkwargs,"unexpected keyword arguments for `random_size_crop`."ifisinstance(area,numeric_types):area=(area,1.0)for_inrange(10):target_area=random.uniform(area[0],area[1])*src_areanew_ratio=random.uniform(*ratio)new_w=int(round(np.sqrt(target_area*new_ratio)))new_h=int(round(np.sqrt(target_area/new_ratio)))ifrandom.random()<0.5:new_h,new_w=new_w,new_hifnew_w<=wandnew_h<=h:x0=random.randint(0,w-new_w)y0=random.randint(0,h-new_h)out=fixed_crop(src,x0,y0,new_w,new_h,size,interp)returnout,(x0,y0,new_w,new_h)# fall back to center_cropreturncenter_crop(src,size,interp)

[docs]classRandomSizedCropAug(Augmenter):"""Make random crop with random resizing and random aspect ratio jitter augmenter. Parameters ---------- size : tuple of (int, int) Size of the crop formatted as (width, height). area : float in (0, 1] or tuple of (float, float) If tuple, minimum area and maximum area to be maintained after cropping If float, minimum area to be maintained after cropping, maximum area is set to 1.0 ratio : tuple of (float, float) Aspect ratio range as (min_aspect_ratio, max_aspect_ratio) interp: int, optional, default=2 Interpolation method. See resize_short for details. """

[docs]classImageIter(io.DataIter):"""Image data iterator with a large number of augmentation choices. This iterator supports reading from both .rec files and raw image files. To load input images from .rec files, use `path_imgrec` parameter and to load from raw image files, use `path_imglist` and `path_root` parameters. To use data partition (for distributed training) or shuffling, specify `path_imgidx` parameter. Parameters ---------- batch_size : int Number of examples per batch. data_shape : tuple Data shape in (channels, height, width) format. For now, only RGB image with 3 channels is supported. label_width : int, optional Number of labels per example. The default label width is 1. path_imgrec : str Path to image record file (.rec). Created with tools/im2rec.py or bin/im2rec. path_imglist : str Path to image list (.lst). Created with tools/im2rec.py or with custom script. Format: Tab separated record of index, one or more labels and relative_path_from_root. imglist: list A list of images with the label(s). Each item is a list [imagelabel: float or list of float, imgpath]. path_root : str Root folder of image files. path_imgidx : str Path to image index file. Needed for partition and shuffling when using .rec source. shuffle : bool Whether to shuffle all images at the start of each iteration or not. Can be slow for HDD. part_index : int Partition index. num_parts : int Total number of partitions. data_name : str Data name for provided symbols. label_name : str Label name for provided symbols. dtype : str Label data type. Default: float32. Other options: int32, int64, float64 last_batch_handle : str, optional How to handle the last batch. This parameter can be 'pad'(default), 'discard' or 'roll_over'. If 'pad', the last batch will be padded with data starting from the begining If 'discard', the last batch will be discarded If 'roll_over', the remaining elements will be rolled over to the next iteration kwargs : ... More arguments for creating augmenter. See mx.image.CreateAugmenter. """

defreset(self):"""Resets the iterator to the beginning of the data."""ifself.seqisnotNoneandself.shuffle:random.shuffle(self.seq)ifself.last_batch_handle!='roll_over'or \
self._cache_dataisNone:ifself.imgrecisnotNone:self.imgrec.reset()self.cur=0ifself._allow_readisFalse:self._allow_read=Truedefhard_reset(self):"""Resets the iterator and ignore roll over data"""ifself.seqisnotNoneandself.shuffle:random.shuffle(self.seq)ifself.imgrecisnotNone:self.imgrec.reset()self.cur=0self._allow_read=Trueself._cache_data=Noneself._cache_label=Noneself._cache_idx=Nonedefnext_sample(self):"""Helper function for reading in next sample."""ifself._allow_readisFalse:raiseStopIterationifself.seqisnotNone:ifself.cur<self.num_image:idx=self.seq[self.cur]else:ifself.last_batch_handle!='discard':self.cur=0raiseStopIterationself.cur+=1ifself.imgrecisnotNone:s=self.imgrec.read_idx(idx)header,img=recordio.unpack(s)ifself.imglistisNone:returnheader.label,imgelse:returnself.imglist[idx][0],imgelse:label,fname=self.imglist[idx]returnlabel,self.read_image(fname)else:s=self.imgrec.read()ifsisNone:ifself.last_batch_handle!='discard':self.imgrec.reset()raiseStopIterationheader,img=recordio.unpack(s)returnheader.label,imgdef_batchify(self,batch_data,batch_label,start=0):"""Helper function for batchifying data"""i=startbatch_size=self.batch_sizetry:whilei<batch_size:label,s=self.next_sample()data=self.imdecode(s)try:self.check_valid_image(data)exceptRuntimeErrorase:logging.debug('Invalid image, skipping: %s',str(e))continuedata=self.augmentation_transform(data)asserti<batch_size,'Batch size must be multiples of augmenter output length'batch_data[i]=self.postprocess_data(data)batch_label[i]=labeli+=1exceptStopIteration:ifnoti:raiseStopIterationreturnidefnext(self):"""Returns the next batch of data."""batch_size=self.batch_sizec,h,w=self.data_shape# if last batch data is rolled overifself._cache_dataisnotNone:# check both the data and label have valuesassertself._cache_labelisnotNone,"_cache_label didn't have values"assertself._cache_idxisnotNone,"_cache_idx didn't have values"batch_data=self._cache_databatch_label=self._cache_labeli=self._cache_idx# clear the cache dataelse:batch_data=nd.zeros((batch_size,c,h,w))batch_label=nd.empty(self.provide_label[0][1])i=self._batchify(batch_data,batch_label)# calculate the paddingpad=batch_size-i# handle padding for the last batchifpad!=0:ifself.last_batch_handle=='discard':raiseStopIteration# if the option is 'roll_over', throw StopIteration and cache the dataelifself.last_batch_handle=='roll_over'and \
self._cache_dataisNone:self._cache_data=batch_dataself._cache_label=batch_labelself._cache_idx=iraiseStopIterationelse:_=self._batchify(batch_data,batch_label,i)ifself.last_batch_handle=='pad':self._allow_read=Falseelse:self._cache_data=Noneself._cache_label=Noneself._cache_idx=Nonereturnio.DataBatch([batch_data],[batch_label],pad=pad)defcheck_data_shape(self,data_shape):"""Checks if the input data shape is valid"""ifnotlen(data_shape)==3:raiseValueError('data_shape should have length 3, with dimensions CxHxW')ifnotdata_shape[0]==3:raiseValueError('This iterator expects inputs to have 3 channels.')defcheck_valid_image(self,data):"""Checks if the input data is valid"""iflen(data[0].shape)==0:raiseRuntimeError('Data shape is wrong')defimdecode(self,s):"""Decodes a string or byte string to an NDArray. See mx.img.imdecode for more details."""deflocate():"""Locate the image file/index if decode fails."""ifself.seqisnotNone:idx=self.seq[(self.cur%self.num_image)-1]else:idx=(self.cur%self.num_image)-1ifself.imglistisnotNone:_,fname=self.imglist[idx]msg="filename: {}".format(fname)else:msg="index: {}".format(idx)return"Broken image "+msgtry:img=imdecode(s)exceptExceptionase:raiseRuntimeError("{}, {}".format(locate(),e))returnimgdefread_image(self,fname):"""Reads an input image `fname` and returns the decoded raw bytes. Examples -------- >>> dataIter.read_image('Face.jpg') # returns decoded raw bytes. """withopen(os.path.join(self.path_root,fname),'rb')asfin:img=fin.read()returnimgdefaugmentation_transform(self,data):"""Transforms input data with specified augmentation."""forauginself.auglist:data=aug(data)returndatadefpostprocess_data(self,datum):"""Final postprocessing step before image is loaded into the batch."""returnnd.transpose(datum,axes=(2,0,1))