Skip to main content

Detecting and drawing contours | Android Document Scanner

After you have set up the ScanbotCameraView the next logical step would be to start using contour detection and draw the results on the screen.

Some background#

ScanbotCameraView has a method getPreviewBuffer() which allows you to register for preview frames from the camera. While you can implement your own smart features, the Scanbot SDK comes with built-in ContourDetectorFrameHandler which performs contour detection and then outputs results to listeners.

Contour detection#

To start contour detection, you have to attach the ContourDetectorFrameHandler to the preview buffer:

val detector: ContourDetector = ScanbotSDK(context).createContourDetector()val cameraView = findViewById<ScanbotCameraView>(R.id.cameraView)
val frameHandler = ContourDetectorFrameHandler(context, detector)cameraView.previewBuffer.addFrameHandler(frameHandler)

or even shorter

val detector: ContourDetector = ScanbotSDK(context).createContourDetector()val frameHandler = attach(cameraView, detector)

At this point, the contour detection becomes active. Now all we have to do is wait for the results:

frameHandler.addResultHandler(ContourDetectorFrameHandler.ResultHandler { result ->    when (result) {        is FrameHandlerResult.Success -> {            //handle result here result.value.detectionResult        }        is FrameHandlerResult.Failure -> {              //there is a license problem that needs to be handled        }    }    false})

Contour detection parameters#

You can easily control the contour detection sensitivity by modifying the optional parameters in ContourDetectorFrameHandler:

    val detector: ContourDetector = ScanbotSDK(context).createContourDetector()    val frameHandler = attach(cameraView, detector)    frameHandler.setAcceptedAngleScore(75.0)    frameHandler.setAcceptedSizeScore(80.0)

setAcceptedAngleScore(acceptedAngleScore: Double) - set the minimum score in percentage (0 - 100) of the perspective distortion to accept a detected document. The default value is 75.0. You can set lower values to accept more perspective distortion.

Warning: Lower values result in document images which are more blurred.

setAcceptedSizeScore(acceptedSizeScore : Double) - set the minimum size in percentage (0 - 100) of the screen size to accept a detected document. It is sufficient that either the height or the width match the score. The default value is 80.0.

Warning: Lower values result in lower resolution document images.

Drawing detected contour#

To draw the detected contour use PolygonView. First, add it as a sub-view of ScanbotCameraView:

<io.scanbot.sdk.camera.ScanbotCameraView    android:id="@+id/cameraView"    android:layout_width="match_parent"    android:layout_height="match_parent">
    <io.scanbot.sdk.ui.PolygonView        android:id="@+id/polygonView"        android:layout_width="match_parent"        android:layout_height="match_parent"        app:polygonStrokeWidth="8dp"        app:polygonStrokeColor="#ffffff"        app:polygonFillColor="#00ff00" />
</io.scanbot.sdk.camera.ScanbotCameraView>

Second, PolygonView should receive callbacks from ContourDetectorFrameHandler:

val polygonView = findViewById<PolygonView>(R.id.polygonView)frameHandler.addResultHandler(polygonView.contourDetectorResultHandler)

Customizing drawn polygon#

PolygonView supports the following attributes (which you can add in XML, as shown in the example above):

  • polygonStrokeWidth - width (thickness) of polygon lines
  • polygonStrokeColor - color of polygon lines
  • polygonFillColor - fill color of polygon
  • polygonStrokeColorOK - color of polygon lines when detection is successful (optional)
  • polygonFillColorOK - fill color of polygon when detection is successful (optional)
  • polygonAutoSnapStrokeWidth - width of autosnapping polygon progress indicator (default 3dp)
  • polygonAutoSnapingProgressStrokeColor - color of autosnapping polygon progress indicator (default is white)
  • polygonRoundedCornersRadius - possible polygon rounded corner radius (0 by default)
  • drawShadow - whether polygon stroke should cast shadow (since Android API v26) (default is false)