Here we put together functions from previous articles to describe a use case where objects are discovered in an image and rotated.
All code is available on GitHub under the GoatImage project.
Related Articles:
- JavaCV Basics: IplImage
- Contouring
- JavaCV Basics: Rotation
- Cropping
- JavaCV Basics: Basic Image Processing
Why Split Objects
At times, objects need to be tracked reliably, OCR needs to be broken down to more manageable tasks, or there is another task requiring splitting and rotation. Particularly, recognition and other forms of statistical computing benefit from such standardization.
Splitting allows object by object recognition which may or may not improve accuracy depending on the data used to train an algorithm and even the type of algorithm used. Bayesian based networks, including RNNs, benefit from this task significantly.
Splitting and Rotating
The following function in GoatImage performs contouring to find objects, creates minimum area rect, and finally rotates objects based on their skew angle.
/** * Split an image using an existing contouring function. Take each RIO, rotate, and return new Images with the original, * * @param image The image to split objects from * @param contourType The contour type to use defaulting to CV_RETR_EXTERNAL * @param minBoxArea Minumum box area to accept (-1 means everything and is default) * @param maxBoxArea Maximum box area to accept (-1 means everything and is default) * @param show Whether or not to show the image. Default is false. * @param xPosSort Whether or not to sort the objects by their x position. Default is true. This is faster than a full sort * @return A tuple with the original Image and a List of split out Image objects named by the original_itemNumber */ def splitObjects(image : Image, contourType : Int= CV_RETR_LIST,minBoxArea : Int = -1, maxBoxArea : Int = -1, show : Boolean= false,xPosSort : Boolean = true):(Image,List[(Image,BoundingBox)])={ //contour val imTup : (Image, List[BoundingBox]) = this.contour(image,contourType) var imObjs : List[(Image,BoundingBox)] = List[(Image,BoundingBox)]() var boxes : List[BoundingBox] = imTup._2 //ensure that the boxes are sorted by x position if(xPosSort){ boxes = boxes.sortBy(_.x1) } if(minBoxArea > 0){ boxes = boxes.filter({x => (x.width * x.height) > minBoxArea}) } if(maxBoxArea > 0){ boxes = boxes.filter({x => (x.width * x.height) < maxBoxArea}) } //get and rotate objects var idx : Int = 0 for(box <- boxes){ println(box) val im = this.rotateImage(box.image,box.skewAngle) if(show){ im.showImage(s"My Box ${idx}") } im.setName(im.getName().replaceAll("\\..*","")+s"_${idx}."+im.itype.toString.toLowerCase()) imObjs = imObjs :+ (im,box) idx += 1 } (image,imObjs) }
Contours are filtered after sorting if desired. For each box, rotation is performed and the resulting image returned as a new Image.
Conclusion
Here the splitObjects function of GoatImage is reviewed, revealing how the library and OpenCV splits and rotates objects as part of standardization for object recognition and OCR.
6 thoughts on “JavaCV Basics: Splitting Objects”