Opencv Guide

Learn how to highlighting Objects in a Picture with OpenCV through Logisland Records.

This guide covers:

  • OpenCV API

  • object highlighting

1. Prerequisites

To complete this guide, you need:

  • less than 15 minutes

  • an IDE

  • JDK 1.8+ installed with JAVA_HOME configured appropriately

  • to be familiar with logisland (please refer to other guides first otherwise)

2. Solution

Clone the Git repository: git clone https://github.com/hurence/logisland-quickstarts.git, or download an archive.

The logisland job is located in the conf/computer-vision/opencv.yml file.

3. Environment setup

Start all the the services with the following command sudo docker-compose -f docker-compose.yml -f docker-compose.opencv.yml -d

4. Setup Logisland Job

Run directly the solution wioth the following command within the https://github.com/hurence/logisland-quickstarts.git root folder.

sudo docker exec -ti logisland-quickstarts_logisland_1 ./bin/logisland.sh --conf conf/computer-vision/opencv.yml

5. the timeseries app

here is the logisland job for timeseries parsing, chunking and indexing

version: 1.2.0
documentation: LogIsland computer vision sample

engine:
  component: com.hurence.logisland.engine.spark.KafkaStreamProcessingEngine
  configuration:
    spark.app.name: OpenCV
    spark.master: local[2]
    spark.streaming.batchDuration: 200
    spark.streaming.kafka.maxRatePerPartition: 10000
    spark.streaming.timeout: -1

  controllerServiceConfigurations:

    - controllerService: kafka_service
      component: com.hurence.logisland.stream.spark.structured.provider.KafkaStructuredStreamProviderService
      configuration:
        kafka.input.topics: logisland_raw
        kafka.output.topics: logisland_images
        kafka.error.topics: logisland_errors
        kafka.input.topics.serializer: none
        kafka.output.topics.serializer: none
        kafka.error.topics.serializer: com.hurence.logisland.serializer.JsonSerializer
        kafka.metadata.broker.list: kafka:9092
        kafka.zookeeper.quorum: zookeeper:2181
        kafka.topic.autoCreate: true
        kafka.topic.default.partitions: 2
        kafka.topic.default.replicationFactor: 1

  streamConfigurations:

    - stream: parsing_stream
      component: com.hurence.logisland.stream.spark.structured.StructuredStream
      configuration:
        read.topics.serializer: com.hurence.logisland.serializer.BytesArraySerializer
        read.stream.service.provider: kafka_service
        write.topics.serializer: com.hurence.logisland.serializer.BytesArraySerializer
        write.stream.service.provider: kafka_service
      processorConfigurations:

        - processor: contour_extraction
          component: com.hurence.logisland.cv.processor.RunScript
          configuration:
            input.field: record_value
            output.field: record_value
            output.mode: overwrite
            image.format: png
            script.ns: com.hurence.logisland
            script.function: ld_detect_edges
            script.code: >
              (ns com.hurence.logisland
                (:refer-clojure :exclude [sort min merge reduce max compare repeat])
                (:require [opencv4.utils :refer :all])
                (:require [opencv4.core :refer :all])
                (:import [com.hurence.logisland.record Record]))

              (defn ld_detect_edges [mat]
                (-> mat
                    (resize-by 0.5)
                    (cvt-color! COLOR_RGB2GRAY)
                    (canny! 300.0 100.0 3 true)
                    (bitwise-not!)))

6. some data to process

The loggen container send some raw values into logisland_raw topic

If you want to see what is flowing into logisland_raw topic, just run the following :

sudo docker exec -ti logisland-quickstarts_kafka_1 /opt/kafka/bin/kafka-console-consumer.sh --bootstrap-server kafka:9092 --topic logisland_raw

7. get the output from kafka to a file

TODO : add a python script to save those iamges from kafka to files

8. Problem

You have a picture with a set of objects, animals, or shapes that you would like to highlight, maybe because you want to count them.

9. Solution

OpenCV offers a famous function named Canny, which can highlight lines in a picture. You will see how to use canny in more detail later in this chapter; for now, let’s focus on the basic steps using Java.

OpenCV’s canny works on gray mat for contour detection. While you can leave it to canny to do it for you, let’s explicitly change the color space of the input mat to be in grayspace.

Changing color space is easily done with OpenCV using the cvtColor function found in the Core class.

10. How it works

Suppose you have a picture as a byte array in record’s field :

We start by loading the picture into a Mat as usual:

to resize the picture right after loading

(resize-by 0.5)

We then convert the color of that tools mat using the cvtColor function, which takes a source mat, a target mat, and a target color space. Color space constants are found in the Imgproc class and have a prefix like COLOR_.

So to turn the mat to black and white, you can use the COLOR_ RGB2GRAY constant.

(cvt-color! COLOR_RGB2GRAY)

The black-and-white picture is ready to be sent to canny. Parameters for the canny function are as follows:

  • Source mat

  • Target mat

  • Low threshold: we will use 150.0

High threshold: usually approximately low threshold*2 or low threshold*3 Aperture: an odd value between 3 and 7; we will use 3. The higher the aperture, the more contours will be found.

L2Gradient value, for now set to true

Canny computes a gradient value for each pixel, using a convolution matrix with the center pixels and neighboring pixels. If the gradient value is higher than the high threshold, then it is kept as an edge. If it’s in between, it is kept if it has a high gradient connected to it.

Now, we can call the Canny function.

(canny! 150.0 300.0 3 true)

For the eyes, the printer, and the trees, it may be sometimes easier to draw the inverted Mat where white is turned to black, and black is turned to white. This is done using the bitwise_not function from the Core class.

(bitwise-not!)))
(ns com.hurence.logisland
  (:refer-clojure :exclude
                  [sort min merge reduce max compare repeat])
  (:require [opencv4.utils :refer :all])
  (:require [opencv4.core :refer :all])

(defn ld_detect_edges [mat]
  (-> mat
      (resize-by 0.5)
      (cvt-color! COLOR_RGB2GRAY)
      (canny! 150.0 300.0 3 true)
      (bitwise-not!)))

11. Cleanup

to remove all containers run the following

sudo docker-compose -f docker-compose.yml -f docker-compose.opencv.yml down