728x90
어제는 이미지를 해 보았으니, 동영상 조작을 해 볼까 합니다.
우선 동영상 용 액션 커맨드로 추가 하겠습니다.
final class ThemeButtonPanel extends JPanel {
private static final long serialVersionUID = 1101056225940013101L;
ThemeButtonPanel(final UsrSelectOptions usrOptions) {
setLayout(new GridLayout(1, 3));
//setSize(new Dimension(100, 450));
//setPreferredSize(new Dimension(100, 450));
initButtonPane(usrOptions);
}
void initButtonPane(final UsrSelectOptions usrOptions) {
JButton goImage = new JButton("Go image~");
JButton goMovie = new JButton("Go Movie~");
JButton goCam = new JButton("Go Camera~");
if(usrOptions.isCanvas)
{
goImage.setActionCommand("goImageCanvas");
goMovie.setActionCommand("goMovieCanvas");
}
else
{
goImage.setActionCommand("goImagePanel");
goMovie.setActionCommand("goMovieCanvas");
}
add(goImage);
add(goMovie);
add(goCam);
goImage.addActionListener(btnListener);
}
}
동영상 파일을 로딩 하는 것도 추가 하고요~
class MainButtonClickListener implements ActionListener {
...
@Override
public void actionPerformed(ActionEvent e) {
...
else if (e.getActionCommand().equals("goMovieCanvas")) {
if(!isStop) mSelectedFile = selectFileGui("Movie");
movieCanvas.loadImage(mSelectedFile, isStop);
}else if (e.getActionCommand().equals("goMoviePanel")) {
if(!isStop) mSelectedFile = selectFileGui("Movie");
moviePanel.loadImage(mSelectedFile, isStop);
}
}
}
movieCanvas 인스턴스와 moviepanel 인스턴스를 위한 클래스를 만들어야 겠네요
우선 movieCanvas 는 ImageCanvas와 같은 방식으로 만들 생각이예요
대신 메서드 이름이 조금 바뀌겠죠?
이렇게... moviePanel 의 경우에도 행동 즉 메서드는 똑 같을 것이라고도 예상 될 것입니다.
abstract class MovieCanvas extends Canvas
{
abstract void setThemeButton(JButton currentBtn);
abstract void stopTimer();
abstract void loadMovie(String imagePath, boolean isStop);
abstract void loadMovie(int drawingStyle);
abstract void loadMovie(int drawingStyle, CannyOption cannyOption);
}
그래서 가만히 생각 해 보니, 캔버스와 패널로 나누어서 코드를 작성하다가
이 둘이 하는 행동 즉 메서드는 똑 같겠다? 라는 생각이 들어요
그래서 이런 행동을 먼저 정희 해 두는 인터페이스를 부모로 두면 될 것이라는 생각이 들었습니다.
그래서 다음 인터페이스를 만들어 보았어요
interface ImageProcessing
{
void setThemeButton(JButton currentBtn);
void stopTimer();
void loadMovie(String imagePath, boolean isStop);
void loadMovie(int drawingStyle);
void loadMovie(int drawingStyle, CannyOption cannyOption);
}
그리고 MovieCanvas 는 이렇게 바꿀꺼예요
abstract class MovieCanvas extends Canvas implements ImageProcessing
{
public abstract void setThemeButton(JButton currentBtn);
public abstract void stopTimer();
public abstract void loadMovie(String imagePath, boolean isStop);
public abstract void loadMovie(int drawingStyle);
public abstract void loadMovie(int drawingStyle, CannyOption cannyOption);
}
그런다음 해당 하는 행동을 하는 클래스를 만들어야 합니다.
우선, initImagePanel 메서드는 클래스를 추가해서 다음과 같이 만들 수 있을 거예요
private void initImagePanel(final UsrSelectOptions usrOptions) {
setLayout(new BorderLayout());
btnListener = new MainButtonClickListener(usrOptions);
btnFuncListener = new FunctionButtonClickListener(usrOptions);
JPanel btnFuncPane = new FuncButtonPanel();
JPanel btnCtrlPane = new ThemeButtonPanel(usrOptions);
if(usrOptions.getThemeType().equals("Image"))
{
if(usrOptions.isCanvas)
{
if(usrOptions.isDoubleBuffering)
imageCanvas = new ImageCanvasDoubleBuffer();
else
imageCanvas = new ImageCanvasNoDoubleBuffer();
add(imageCanvas, BorderLayout.CENTER);
}
else
{
imagePanel = new ImagePanel();
add(imagePanel, BorderLayout.CENTER);
}
} else if(usrOptions.getThemeType().equals("Movie"))
{
if(usrOptions.isCanvas)
{
if(usrOptions.isDoubleBuffering)
movieCanvas = new MovieCanvasDoubleBuffer();
else
movieCanvas = new MovieCanvasNoDoubleBuffer();
add(movieCanvas, BorderLayout.CENTER);
}
else
{
moviePanel = new MoviePanel();
add(moviePanel, BorderLayout.CENTER);
}
}
add(btnCtrlPane, BorderLayout.SOUTH);
add(btnFuncPane, BorderLayout.WEST);
}
차례 차례로 MovieCanvasDoubleBuffer, MovieCanvasNoDoubleBuffer 와 MoviePanel을 만들어 보도록 합니다. 이 클래스들도 사실 별반 내용이 다를 것이 없어서 하나만 본다면 다음과 같은 느낌이 되겠죠?
class MovieCanvasDoubleBuffer extends MovieCanvas {
private boolean movieActive = false;
private BufferedImage bufImagew;
private JButton mThemeButton;
public MovieCanvasDoubleBuffer()
{
super();
}
public void setThemeButton(final JButton themeButton)
{
mThemeButton = themeButton;
}
@Override
public void update(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
Graphics offgc;
Image offscreen;
if (bufImagew != null) {
offscreen = createImage(getWidth(), getHeight());
offgc = offscreen.getGraphics();
offgc.setColor(getBackground());
offgc.drawImage(bufImagew, 0, 0, getWidth(), getHeight(), null);
offgc.setColor(getBackground());
g2.drawImage(offscreen, 0, 0, getWidth(), getHeight(), null);
}
}
public void loadMovie(String moviePath, boolean isStop) {
if(!isStop && StringUtil.isNullOrEmpty(moviePath))
{
JOptionPane.showMessageDialog(null, "동영상 이름을 찾을 수가 없습니다.[" +moviePath+ "]", "이름없음",
JOptionPane.INFORMATION_MESSAGE);
return;
}
else
{
if(!isStop && !new File(moviePath).exists())
{
JOptionPane.showMessageDialog(null, "동영상 경로를 찾을 수가 없습니다. [" + moviePath + "]", "파일 없음.",
JOptionPane.INFORMATION_MESSAGE);
return;
}
}
if (!this.movieActive) {
openMovie(moviePath);
if (isMovieOpened()) {
movieActive = true;
Runnable frameGrabber = new Runnable() {
@Override
public void run() {
Mat frame = grabFrame();
bufImagew = Utils.matToBufferedImage(frame);
repaint();
}
};
scheduleStart(frameGrabber);
mThemeButton.setText("Stop Movie");
} else {
System.err.println("Impossible to open the camera connection...");
}
} else {
this.movieActive = false;
mThemeButton.setText("Start Movie");
stopAcquisition();
}
}
public void loadMovie(int drawingStyle) {
if (!this.movieActive) {
if (isMovieOpened()) {
movieActive = true;
Runnable frameGrabber = new Runnable() {
@Override
public void run() {
Mat frame = grabFrame(drawingStyle);
bufImagew = Utils.matToBufferedImage(frame);
repaint();
}
};
scheduleStart(frameGrabber);
mThemeButton.setText("Stop Movie");
} else {
System.err.println("Impossible to open the camera connection...");
}
} else {
this.movieActive = false;
mThemeButton.setText("Start Movie");
stopAcquisition();
}
}
public void loadMovie(int drawingStyle, CannyOption cannyOpt) {
if (!this.movieActive) {
if (isMovieOpened()) {
movieActive = true;
Runnable frameGrabber = new Runnable() {
@Override
public void run() {
Mat frame = grabFrame(drawingStyle, cannyOpt);
bufImagew = Utils.matToBufferedImage(frame);
repaint();
}
};
scheduleStart(frameGrabber);
mThemeButton.setText("Stop Movie");
} else {
System.err.println("Impossible to open the camera connection...");
}
} else {
this.movieActive = false;
mThemeButton.setText("Start Movie");
stopAcquisition();
}
}
private ScheduledExecutorService timer;
private VideoCapture capture = new VideoCapture();
boolean openMovie(final String moivePath) {
return capture.open(moivePath);
}
boolean isMovieOpened() {
return capture.isOpened();
}
void scheduleStart(Runnable frameGrabber) {
{
timer = Executors.newSingleThreadScheduledExecutor();
timer.scheduleAtFixedRate(frameGrabber, 0, 33, TimeUnit.MILLISECONDS);
}
}
Mat grabFrame() {
return grabFrame(RGBA_DRAWING, null);
}
Mat grabFrame(int drawingStyle) {
return grabFrame(drawingStyle, null);
}
Mat grabFrame(int drawingStyle, CannyOption cannyOpt) {
Mat frame = new Mat();
if (capture.isOpened()) {
try {
capture.read(frame);
if (!frame.empty()) {
switch (drawingStyle) {
case GRAY_SCALE_DRAWING:
Imgproc.cvtColor(frame, frame, Imgproc.COLOR_BGR2GRAY);
break;
case CANNY_DRAWING:
if(cannyOpt !=null)
{
CannyFunction.SetCannyLoLimit(cannyOpt.getLowVal());
CannyFunction.SetCannyHiLimit(cannyOpt.getHighVal());
CannyFunction.SetInverted(cannyOpt.isInv());
}
frame = CannyFunction.Canny(frame);
break;
case BLACK_AND_WHITE_DRAWING:
frame = CannyFunction.BlackAndWhite(frame, 3);
break;
case RGBA_DRAWING:
}
}
} catch (Exception e) {
System.err.println("Exception during the image elaboration: " + e);
}
}
return frame;
}
public void stopTimer() {
movieActive = false;
if (timer != null && !timer.isShutdown()) {
try {
timer.shutdown();
timer.awaitTermination(33, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.err.println("Exception in stopping the frame capture, trying to release the camera now... " + e);
}
}
}
public void stopAcquisition() {
stopTimer();
if (capture.isOpened()) {
// release the camera
capture.release();
}
}
}
그런 다음 실행 봅니다. 결과는 동영상으로 확인 할께요~~
이상.
728x90
'프로그래밍 > [Java] OpenCV' 카테고리의 다른 글
[1] OpenCV-JavaGUI (2) | 2024.01.15 |
---|---|
OpenCV와 자바 - 4.3. 카메라 조작 (0) | 2022.09.17 |
OpenCV와 자바 - 4.1. 이미지 조작 - 2 (0) | 2022.09.15 |
OpenCV와 자바 - 4.1. 이미지 조작 - 1 (0) | 2022.09.14 |
OpenCV와 자바 - 4. 동영상과 이미지 UI-1 (1) | 2022.09.13 |