ทำ Docker Image Java ที่ใช้ OpenCv ได้

ทำ Docker Image Java ที่ใช้ OpenCv ได้

ในปัจจุบันเทคโนโลยีที่เกี่ยวกับการประมวลผลภาพกำลังเป็นที่นิยมไม่ว่าจะเป็นการตรวจจับใบหน้าแล้วเอาไปตรวจสอบกับฐานข้อมูลว่าเป็นคนคนเดียวกันไหม หรือนำภาพไปหาว่าในภาพนั้นมีอะไรอยู่ในภาพนั้นบ้าง ซึ่งเป็นอะไรที่ดูว้าวแล้วเอาไปใช้ทำอะไรได้มากมาย ตัวอย่างที่ใช้กันบ่อยก็คือ ถ่ายรูปหน้า กับรูปบัตรประชาชน แล้วเทียบกันว่าใช่คนเดียวกันไหม หรือตั้งกล้องไว้หน้าบริษัทแล้วทำการตรวจสอบหน้าว่าใช่คนในบริษัทไหม ถ้าใช่ถึงเปิดประตูให้เข้า

OpenCv

OpenCv คือตัว Open Source Lib ที่ใช้ในการประมวลผลภาพที่เปิดให้เราใช้ได้แบบฟรีๆ (ต้องขอขอบคุณเหล่า Dev ทั่วโลกที่ร่วมด้วยช่วยกันสร้างของดีแบบนี้ให้ใช้แบบฟรีๆ) แล้วก็มีคนเอาไปใช้มากมาย มีคนทำตัวเชื่อมให้สามารถใช้กับหลายๆภาษาไม่ว่าจะเป็น Java , Python สามารถใช้บน Windows, Linux , Mac

แล้วจะทำ Docker Image ยังไงล่ะ

ทุกอย่างดูสวยหรูแต่ปัญหาของผมคือแล้วจะทำ Docker Image ยังไงวะ วิธีที่ง่ายที่สุดคือหา Official Docker Image ว่ามันมีที่เป็น Java11 OpenCv version 4.5.1 ไหม ซึ่งปรากฏว่าไม่มีจ้า (มีแต่มีของคนทั่วไปที่เขา Push ขึ้น Dockerhub ไว้ จะเอามาใช้ก็เสี่ยง) ซึ่งด้วยเหตุผลนี้ทำให้ต้องมาทำ Docker Image เอง

ซึ่งจะได้ Dockerfile แบบนี้

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
FROM openjdk:11-jdk AS builder
RUN apt update && apt install -y cmake g++ ant wget unzip

RUN wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.1.zip

RUN mkdir -p /build
RUN unzip opencv.zip -d /
RUN mv opencv-4.5.1 opencv

WORKDIR /build
RUN cmake -DBUILD_SHARED_LIBS=OFF ../opencv
RUN make -j1

FROM openjdk:11-jre

COPY --from=builder /build/lib/libopencv_java451.so /usr/lib
COPY --from=builder /build/bin/opencv-451.jar /usr/lib

เดี๋ยวค่อยๆ อธิบายกัน

1
FROM openjdk:11-jdk AS builder

ตัว Build นี้นั้นผมทำเป็น Multi-stage Build โดย stage builder นั้นจะต้องทำการ Compile ตัว Lib OpenCv ให้อยู่ในรูปที่สามารถนำไปใช้งานได้เลยก่อน แล้วค่อยเอาไปใส่อีก stage ที่จะเอาไปเป็น Image เพื่อใช้งาน โดยส่วนนี้ต้องใช้เป็น openjdk:11-jdk ก่อนเพราะตอน Compile Lib ไปใช้นั้น Ant ในการ compile ตัว Code ของ Java ก็เลยต้องใช้เป็น JDK

1
RUN apt update && apt install -y cmake g++ ant wget unzip

ส่วนนี้คือการ Download lib ที่จำเป็นในการ Download source code แล้วก็ compile

1
2
3
4
5
6
7
RUN wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.1.zip

RUN mkdir -p /build
RUN unzip opencv.zip -d /
RUN mv opencv-4.5.1 opencv

WORKDIR /build

ส่วนนี้คือการ Download Source code ของ OpenCv version 4.5.1 มาจากนั้นทำการแตก zip ให้อยู่ใน directory ที่ต้องการ

1
RUN cmake -DBUILD_SHARED_LIBS=OFF ../opencv

ส่วนนี้คือคำสั่ง Config ว่าจะ Compile แบบไหน โดยตัว -DBUILD_SHARED_LIBS=OFF อันนี้เป็นการบอกว่าเราจะทำการ Compile แบบไม่ใช้ share lib คือ build แล้วทุกอย่างเป็นไฟล์เดียว เอาไปวางแล้วใช้งานได้เลย (ต้องเป็น platform เดียวกันกับตัวที่ build ด้วยนะ ไม่ใช่ build บน windows เอาไปใช้บน Linux แบบนี้ไม่ได้นะ (ตัว Linux แต่ละ Distro อาจไม่เหมือนกันด้วย ดังนั้นใช้ Distro ไหนก็ควรใช้ Distro นั้น Version นั้นในการ compile ))

1
RUN make -j1

ส่วนนี้จะเป็นการเริ่ม compile code โดย -j คือการบอกว่าอนุญาตให้ทำงานแบบ parallel โดยของผม set ไว้ที่ 1 เพราะ cpu ของเครื่อง VM ทดลองผมมีแค่ core เดียว ถ้าใครเครื่องแรงจะ compile หลายๆ core พร้อมกันก็เปลี่ยน -j เป็นจำนวน core ที่อยาก parallel นะครับ โดยผลลัพธ์การ compile ทั้งหมดจะอยู่ใน directory /build

1
FROM openjdk:11-jre

ส่วนนี้คือการสร้าง Image ที่จะเอาไปเป็นตัวตั้งต้นให้ตัว java ที่อยากจะใช้งาน opencv เอาไปใช้งาน จะเห็นว่าใช้ openjdk:11-jre แทนเพราะ java ที่ต้องการ Run อย่างเดียวไม่ต้องการทำการ compile จึงไม่จำเป็นต้องใช้ JDK

1
2
COPY --from=builder /build/lib/libopencv_java451.so /usr/lib
COPY --from=builder /build/bin/opencv-451.jar /usr/lib

ส่วนนี้คือการเอาไฟล์ที่ได้จาก compile จาก stage build มาใส่ใน docker image ที่เราจะเอาไปใช้

เมื่อเข้าใจทุกอย่างแล้วก็สั่ง Build

1
docker build -t jre11-opencv4.5.1

การ Build ใช้เวลานานประมาณนึง (ของผมใช้เวลาประมาณ 1 ชั่วโมง)

ทดลองใช้งาน

คุณสามารถลองใช้งานโดยการเขียน code ง่ายๆ Load lib ของ OpenCv มาใช้งานโดยสามารถดูได้ที่ตัวอย่าง https://www.baeldung.com/java-opencv โดยการที่เราจะใช้ opencv version ไหนนั้นขึ้นอยู่กับตัว lib ที่เรามาใช้ว่าเขาใช้ version ไหนโดยจากตัวอย่างเราใช้ lib ของ https://mvnrepository.com/artifact/org.openpnp/opencv โดยผมใช้ OpenCv version 4.5.1 ดังนั้นผมจึงต้องใช้ lib ที่ support

สรุป

สำหรับตอนนี้เราได้รู้วิธีการ Build Image OpenCv มาใช้งานแล้ว ซึ่งที่ผมมาเขียนตอนนี้เพราะตอนทำงานต้องใช้แล้วมันไม่มีคนทำเลย ใน Internet ก็ไม่มีคนเขียนอธิบายไว้เลย ก็เลยมาเขียนอธิบายเลยละกัน คนอื่นๆที่ติดปัญหาเหมือนกันจะได้ไม่ต้องเสียเวลา ค้นหาลองผิดลองถูกให้เสียเวลา

Ref

เพลงประกอบการเขียน Code

โดยส่วนตัวผมชอบ MV เพลงนี้มาก ผมชอบตรงความจริงของมัน มันไม่สวยงาม มันคือเรื่องจริงที่เราอาจได้เจอ แต่ผมนับถือใจตัวพระเอกนะที่มีวิธีจัดการกับเหตุการณ์แบบนี้ได้ดี