I have made a simple scala application that uses OpenCV-4.8.0 that extract face from image via Haar-Cascade (haarcascade_frontalface_default.xml).
The above functionality working fine on local machine.
Now I’m trying to achieve same functionality through dockerization, for this I’ve followed, following steps.
Here is the build.sbt, in which we are creating an Image via sbt-native-packager and then installed OpenCV-4.8.0 via dockerCommands.
import com.typesafe.sbt.packager.docker._
ThisBuild / version := "0.1.0-SNAPSHOT"
ThisBuild / scalaVersion := "2.13.4"
lazy val root = (project in file("."))
.settings(
name := "human-verification-scala-service"
)
unmanagedBase := file("opencv4")
enablePlugins(JavaAppPackaging, DockerPlugin)
Docker / packageName := "human-verification-test"
Universal / javaOptions += "-Djava.library.path=/opencv4"
Docker / version := "0.0.1"
dockerExposedPorts := Seq(8083)
dockerChmodType := DockerChmodType.UserGroupWriteExecute
dockerPermissionStrategy := DockerPermissionStrategy.CopyChown
dockerAdditionalPermissions += (DockerChmodType.UserGroupPlusExecute, "/var/run/")
Docker / daemonUserUid := None
Docker / daemonUser := "root"
dockerBaseImage := "amazoncorretto:11-alpine3.18-jdk"
dockerCommands ++= Seq(
Cmd("RUN", "apk", "add", "--no-cache", "bash make cmake g++ wget unzip"),
Cmd("RUN", "apk", "add", "--no-cache", "linux-headers"),
Cmd("RUN", "wget", "-O", "opencv.zip", "https://github.com/opencv/opencv/archive/4.8.0.zip"),
Cmd("RUN", "unzip", "opencv.zip && rm opencv.zip"),
Cmd("RUN", "mkdir", "-p", "build && cd build && cmake ../opencv-4.8.0 && make -j4 && make install")
)
fork := true
libraryDependencies ++= Seq(
"com.typesafe" % "config" % "1.4.2",
"com.typesafe.akka" %% "akka-actor" % "2.6.0",
"com.typesafe.akka" %% "akka-stream" % "2.7.0",
"com.typesafe.akka" %% "akka-http" % "10.5.2",
"ch.qos.logback" % "logback-classic" % "1.4.11",
"com.typesafe.akka" %% "akka-http-spray-json" % "10.5.2",
"io.netty" % "netty-transport-native-epoll" % "4.1.99.Final" classifier "linux-x86_64"
)
→ Here in opencv4 directory we have .jar and .so files of OpenCV-4.8.0 for compiling code, and I’m creating it’s docker volume.
→ OpenCV is working fine in docker as I’ve tested it in another project as well.
Here is the code:
object CropImage extends App {
def getFace(imagePath: String): Mat = {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME)
val faceCascade = new CascadeClassifier("/opt/docker/opencv-4.8.0/data/haarcascades/haarcascade_frontalface_default.xml")
val image = Imgcodecs.imread(imagePath)
val gray = new Mat()
Imgproc.cvtColor(image, gray, Imgproc.COLOR_BGR2GRAY)
val faces = new MatOfRect()
faceCascade.detectMultiScale(gray, faces)
if (!faces.empty()) {
val faceRectArray = faces.toArray
val faceRect = faceRectArray(0)
val padding = 220
val startY = Math.max(0, faceRect.y - padding)
val endY = Math.min(image.rows(), faceRect.y + faceRect.height + padding)
val startX = Math.max(0, faceRect.x)
val endX = Math.min(image.cols(), faceRect.x + faceRect.width)
new Mat(image, new Rect(new Point(startX, startY), new Point(endX, endY)))
}
else {
new Mat()
}
}
getFace("/src/main/resources/MyImage.png")
}
→ /opt/docker/opencv-4.8.0/data/haarcascades/haarcascade_frontalface_default.xml is available after installing OpenCV in docker image.
After doing docker:publishLocal in sbt-shell it downloaded OpenCV and created the docker image.
Then I run image using docker-compose up, here is docker-compose.yml:
version: '3'
services:
scala-service:
image: human-verification-test:0.0.1
volumes:
- ./src/main/resources:/src/main/resources
- ./opencv4:/opencv4
ports:
- "8083:8083"
Unfortunately I’m getting an error:
scala-service_1 | # A fatal error has been detected by the Java Runtime Environment:
scala-service_1 | #
scala-service_1 | # SIGSEGV (0xb) at pc=0x00007f6a21b60ca9, pid=1, tid=81
scala-service_1 | #
scala-service_1 | # JRE version: OpenJDK Runtime Environment Corretto-11.0.21.9.1 (11.0.21+9) (build 11.0.21+9-LTS)
scala-service_1 | # Java VM: OpenJDK 64-Bit Server VM Corretto-11.0.21.9.1 (11.0.21+9-LTS, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
scala-service_1 | # Problematic frame:
scala-service_1 | # C [libopencv_java480.so+0x141ca9] Java_org_opencv_objdetect_CascadeClassifier_CascadeClassifier_11+0xf9
scala-service_1 | #
scala-service_1 | # Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /opt/docker/core.1)
scala-service_1 | #
scala-service_1 | # An error report file with more information is saved as:
scala-service_1 | # /opt/docker/hs_err_pid1.log
humanverificationscalaservice_scala-service_1 exited with code 139
here is the hs_err_pid1.log:
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j org.opencv.objdetect.CascadeClassifier.CascadeClassifier_1(Ljava/lang/String;)J+0
j org.opencv.objdetect.CascadeClassifier.<init>(Ljava/lang/String;)V+6
j blurriness.CheckBlurry$.getFace(Ljava/lang/String;Ljava/lang/String;)Lorg/opencv/core/Mat;+11
j blurriness.CheckBlurry$.isImageBlurry(Ljava/lang/String;Ljava/lang/String;)Lscala/Tuple2;+9
j faceverification.FaceVerification$.$anonfun$routes$7(Lscala/util/Try;)Lscala/Function1;+222
j faceverification.FaceVerification$$Lambda$684.apply(Ljava/lang/Object;)Ljava/lang/Object;+4
j akka.http.scaladsl.server.util.ApplyConverterInstances$anon$1.$anonfun$apply$1(Lscala/Function1;Lscala/Tuple1;)Lscala/Function1;+15
j akka.http.scaladsl.server.util.ApplyConverterInstances$anon$1$Lambda$325.apply(Ljava/lang/Object;)Ljava/lang/Object;+8
j akka.http.scaladsl.server.directives.FutureDirectives.$anonfun$onComplete$3(Lscala/Function1;Lakka/http/scaladsl/server/RequestContext;Lscala/util/Try;)Lscala/concurrent/Future;+9
Guide how can I resolve above error, and use haar-cascade in docker container.