OpenCV 가 4.6.0 이 나왔네요..
다운로드 받아서 아무데나 풀어 줍시다
1. 자바 예제
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
public class HelloCV {
public static void main(String[] args){
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat mat = Mat.eye(3, 3, CvType.CV_8UC1);
System.out.println("mat = " + mat.dump());
}
}
2. 환경 설정
환경은 이런 거겠죠?
- 자바 JDK
- OpenCV 자바 라이브러리
- OpenCV 자바 네이티브 라이브러리
위의 환경 설정 말고 뭐가 있는 지 알아 보도록 하겠습니다.
우선 다음과 같이 환경 변수를 잡겠죠?
SET JAVA_HOME=C:\DEV\SDK\JDK\jdk-11.0.9
SET OPENCV_HOME=C:\DEV\SDK\opencv
SET CLASSPATH=%OPENCV_HOME%\build\java\opencv-460.jar;.
SET PATH=%JAVA_HOME%\BIN;.;%OPENCV_HOME%\build\java\x64;%PATH%
자바는 1.8 에서 너무 놀았던 것 같아서 11 로 올려 보겠습니다.
자바 11 다음과 같은 특징이 있다고 하네요...
음... 뭔가 아는 체 하기에는 생소한 단어가 넘 많으네요~
그런 다음 HelloCV.java 라는 파일을 만들고, 위의 코드를 복사해 넣으면 ? 되겠지만...
다음 디렉토리에 거의 비슷하게 있으니
C:\DEV\SDK\opencv\sources\samples\java\eclipse\HelloCV\src\Main.java
위에 껄 사용 해 보도록 하죠.
3. 헬로우 OpenCV
소스 코드를 컴파일 하고 실행을 한 번 해 보면 될 것 같습니다.
어떻게 되는 지는 아래 동영상으로 확인 하시면 될 듯 하네요...
3. 헬로우 OpenCV 카메라
OpenCV로 뭘 할 수 있을까를 공부하다가 어떤 글을 찾아 보든 간에 신기해서 한 번은 따라 해 본다는 만인의 코드가 바로 이 카메라 사용 해 보기 코드가 아닐까 하네요~
3.1 소스의 재구성
JavaFX 로 만들어 진 것인데.. 별로 안 친해서 그냥 코드를 좀 빌려 쓰도록 해 보겠습니다.
젤 손에 익은 Swing 으로 만들까 합니다.
Swing으로 왜 만드냐고 물어보는 사람은 없겠지만,
옛날 이야기 하나 하자면
이 Java 1.2가 나왔을 때, 선 마이크로 시스템즈(?) 에서는 이를 JAVA 2 로 명명하며 엄청나다고 자랑을 했던 기억이 납니다. 그 중심에 이 Swing 이란 게 있었던 것으로 기억이 나네요...
더 깊이 들어가면 잘 알지도 못하지만,
쓰기도 쉽지도 않고,
만들기도 쉽지 않지만,
만들놔도 예쁘지도 않고,
업그레이드 하기도 애매하고
UI 그리기 위한 통합 개발 환경도 거의 없고 등등
그렇게 초창기 내 코딩 인생에 들어와 박히고 나니, 몸이 기억하고 특히나 손가락이 기억을 하네요.
하지만, 처음 부터 만들라면 손사래를 치겠지만 어디서 원하는 껍데기(여기서는 GUI 화면 ㅋ~) 하나 구하면
오히려 하나 씩 만들어가는 재미도 있다능 ~😅
우선 껍데기 코드는 스택 오버플로우에서~~
(전체 코드는 부록 1에서 확인 하십시오)
위 코드를 바탕으로 github의 아래 소스 코드를 이용 하도록 합니다.
3.2 사용자 UI
사용자 UI 에 대한 개념은 아래 처럼 하는 게 저자의 생각인 듯 합니다.
4. 소스 만들기
그럼 소스를 만들어 볼까 합니다.
우선 진입부, 진입 부는 이건 순전한 내 생각입니다만 공식 같은 거죠~
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
initGui();
}
});
}
위의 코드에서 아래 부분은 있어도 되고 없어도 됩니다.
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception useDefault) {
}
위의 코드가 있으면
이렇게 될꺼고, 없으면
이렇게 될테니까요...😁
그럼 initGui 메서드를 만들어 볼까요?
public static void initGui() {
final HelloCamera hellcam = new HelloCamera();
JFrame f = new JFrame("HelloCamera");
// Let the OS handle the positioning!
f.setLocationByPlatform(true);
f.setLayout(new BorderLayout());
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
//f.setVisible(true);
f.add(hellcam, BorderLayout.CENTER);
f.pack();
//f.setSize(new Dimension(800, 600));
f.setVisible(true);
f.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("Closed");
hellcam.stopCam();
e.getWindow().dispose();
}
});
}
위의 코드를 수행 하면, 이미 이렇게 저렇게 만들어 본 위의 윈도우가 나옵니다.
아주 단순해 보이는 말이죠.
문득, 메서드라는 말이 나와서 말인 데 보통 우리는 함수라고도 말을 합니다.
메서드는 방법, 함수는 기능 이라는 영어 단어 인 것으로 보이고
우리는 소프트웨어 공학 중에 OO 로 말하는 것을 방법론이라고 합니다.
그래서 내 생각에는 C 에서는 함수, 그 외에 Object Oriented Programming 을 할 때는 메서드가 아닐까 하는 데요. 자바는 OOP 를 하기 최적화 된 언어 였기 때문에(그때는 😊) 자바는 메서드라고 해도 되지 않을까 하는 순전한 나만의 생각입니다.
그럼 이런 생각이 들기도 하지요. OO 의 개념으로 짜면 메서드, 아니면 함수?
그럼 HelloCamera 클래스를 만들어 볼 차례 입니다.
이 클래스의 뼈대는 다음 처럼 구성이 됩니다. 짜다 보니 아래 같은 뼈대가 되었습니다.
일단, 아무 생각이 없다고 봐야죠~
public class HelloCamera extends JPanel {
private static JButton goCam = new JButton("Go camera~");
private static CamPanel camPane = new CamPanel();
private static CamCanvas camCavs = new CamCanvas();
public HelloCamera(final boolean isCanvas) {
setSize(new Dimension(600, 450));
setPreferredSize(new Dimension(600, 450));
initCamPanel(isCanvas);
setVisible(true);
}
private void initCamPanel(final boolean isCanvas)
{
if(!isCanvas)
{
camPane.setSize(new Dimension(600, 450));
camPane.setPreferredSize(new Dimension(600, 450));
setLayout(new BorderLayout());
add(camPane, BorderLayout.CENTER);
add(goCam, BorderLayout.SOUTH);
goCam.setActionCommand("goCamPanel");
goCam.addActionListener(new CamButtonClickListener());
}
else
{
camCavs.setSize(new Dimension(600, 450));
camCavs.setPreferredSize(new Dimension(600, 450));
setLayout(new BorderLayout());
add(camCavs, BorderLayout.CENTER);
add(goCam, BorderLayout.SOUTH);
goCam.setActionCommand("goCamCanvas");
goCam.addActionListener(new CamButtonClickListener());
}
}
class CamButtonClickListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals("goCamPanel")) {
camPane.startCamera();
}
else if (e.getActionCommand().equals("goCamCanvas")) {
camCavs.startCamera();
}
}
}
protected void stopCam(final boolean isCanvas) {
if(!isCanvas)
{
camPane.stopAcquisition();
}
else
{
camCavs.stopAcquisition();
}
}
final static class CamCanvas extends Canvas {
...
}
final static class CamPanel extends JPanel {
...
}
public static void initGui(final boolean isCanvas) {
...
}
public static void main(String[] args) {
...
}
}
위의 코드를 보면,
private static JButton goCam = new JButton("Go camera~");
private static CamPanel camPane = new CamPanel();
private static CamCanvas camCavs = new CamCanvas();
위와 같이 Panel과 Canvas가 두개 구성 되어 있는 것이 보이 실 겁니다.
이건 카메라에서 받아온 이미지를 그리는 방법이
패널 위에다 그리는 방업과 캔버스에 그리는 방법 두개가 있어서 따로 선언 한 부분입니다.
그리는 방법에 대한 상세한 설명은 공부를 안해봐서 모르겠습니다만,
패널에다 그리는 것은 내부적인 자바 라이브러리를 좀 더 써서 편하게 그리겠다는 의미이고,
캔버스에다 그리는 것은 좀 더 개발자가 자신의 임의 대로 섬세한(?) 그리기를 해 보겠다는 의미로
저는 받아 들입니다.
isCanvas 라는 불리언 매개 변수는 그래서 나온 것이라 생각 하면 됩니다.
여기까지 하겠습니다~아
부록 1.
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.highgui.Highgui;
import org.opencv.highgui.VideoCapture;
public class Robot extends JPanel implements Runnable {
static BufferedImage bufImagew = null;
public Robot() {
JFrame f=new JFrame();
f.setVisible(true);
f.add(this);
f.setSize(new Dimension(640,500));
}
@Override
public void run() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
VideoCapture camera = new VideoCapture(0);
// 1 for next camera
int i = 0;
try {
Mat frame = new Mat();
while (true) {
camera.read(frame);
Mat image_tmp = frame;
MatOfByte matOfByte = new MatOfByte();
BufferedImage bufImage = null;
if(image_tmp!=null)
Highgui.imencode(".jpg", image_tmp, matOfByte);
byte[] byteArray = matOfByte.toArray();
try {
InputStream in = new ByteArrayInputStream(byteArray);
bufImage = ImageIO.read(in);
} catch (Exception e) {
e.printStackTrace();
}
bufImagew=bufImage;
this.repaint();
if(i==5)
i=0;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void paintComponent(Graphics g)
{
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
DetectFaceDemo d=new DetectFaceDemo();
try {
super.paintComponent(g);
g.drawImage(bufImagew,0,0,null);
}
catch(Exception e){}
}
public static void main(String[] args) {
Robot gs = new Robot();
Thread th = new Thread(gs);
th.start();
}
}
부록 2.
'프로그래밍 > [Java] OpenCV' 카테고리의 다른 글
OpenCV와 자바 - 4.1. 이미지 조작 - 1 (0) | 2022.09.14 |
---|---|
OpenCV와 자바 - 4. 동영상과 이미지 UI-1 (1) | 2022.09.13 |
OpenCV와 자바 - 3. 프로세싱-2 (0) | 2022.09.12 |
OpenCV와 자바 - 3. 프로세싱 (2) | 2022.09.11 |
OpenCV와 자바 - 2. 헬로 Camera (0) | 2022.09.09 |