0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

EV3(leJOS)でカメラの映像をPCに送って顔認識をする②

Last updated at Posted at 2020-01-13

EV3から送られてきた画像をPCに表示する

PC側のプログラム

CameraFrame.java
public class CameraFrame {
	private static final int WIDTH = 160;
	private static final int HEIGHT = 120;
	private static final int NUM_PIXELS = WIDTH * HEIGHT;
	private static final int BUFFER_SIZE = NUM_PIXELS * 2;
	private static final int PORT = 55555;

	private ServerSocket ss;
	private Socket sock;
	private byte[] buffer = new byte[BUFFER_SIZE];
	private BufferedInputStream bis;
	private BufferedImage image;
	private CameraPanel panel = new CameraPanel();
	private JFrame frame;

      //ServerSocket,Socket,BufferedInputStreamの準備
        public CameraFrame() {
            try {
                ss = new ServerSocket(PORT);
                sock = ss.accept();
                bis = new BufferedInputStream(sock.getInputStream());
            } catch (Exception e) {
                System.err.println("Failed to connect: " + e);
                System.exit(1);
            }
            image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
	}
        
        //フレームを作成
        public void createAndShowGUI() {
            frame = new JFrame("EV3 Camera View");//JFrameのオブジェクトを作成しタイトルを設定する
            frame.getContentPane().add(panel);//送られてきた画像を描くpanelをframeに追加する.
            frame.setPreferredSize(new Dimension(WIDTH, HEIGHT));//フレームサイズの指定
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//フレームを閉じるときの動作の指定
            //windowをクローズ処理中のときの動作
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {    
                    close();//詳細は下のcloseメソッドを参照
                }
            });
            frame.pack();//frameのサイズをフレーム中のコンポーネントに合わせて調節してくれる
            frame.setVisible(true);//フレームを表示する
        }

        //openしたものをすべてcloseする
        public void close() {
            try {
                if (bis != null)
                    bis.close();
                if (sock != null)
                    sock.close();
                if (ss != null)
                    ss.close();
            } catch (Exception e1) {
                System.err.println("Exception closing window: " + e1);
            }
        }

        //YUVフォーマットをRGBフォーマットへ変換
        private int convertYUVtoARGB(int y, int u, int v) {
            int c = y - 16;
            int d = u - 128;
            int e = v - 128;
            int r = (298 * c + 409 * e + 128) / 256;
            int g = (298 * c - 100 * d - 208 * e + 128) / 256;
            int b = (298 * c + 516 * d + 128) / 256;
            r = r > 255 ? 255 : r < 0 ? 0 : r;
            g = g > 255 ? 255 : g < 0 ? 0 : g;
            b = b > 255 ? 255 : b < 0 ? 0 : b;
            return 0xff000000 | (r << 16) | (g << 8) | b;
        }

        //BufferedInputStreamから1フレーム分のデータを読み取り,imageにRGB形式で格納する.
        public void run() throws IOException {
           while (true) {
               synchronized (this) {
                   try {
                       //bisからデータを読み込む.読み取るデータがまだ入力ストリームに残っているかもしれないのでwhile文を回す.
                       int offset = 0;
                       while (offset < BUFFER_SIZE) {
                           offset += bis.read(buffer, offset, BUFFER_SIZE - offset);
                       }

                       //各ピクセルのyuvフォーマットからrgbに変換してimageへセットする.
                       for (int i = 0; i < BUFFER_SIZE; i += 4) {
                           int y1 = buffer[i] & 0xFF;
                           int y2 = buffer[i + 2] & 0xFF;
                           int u = buffer[i + 1] & 0xFF;
                           int v = buffer[i + 3] & 0xFF;
                           int rgb1 = convertYUVtoARGB(y1, u, v);
                           int rgb2 = convertYUVtoARGB(y2, u, v);
                           image.setRGB((i % (WIDTH * 2)) / 2, i / (WIDTH * 2), rgb1);
                           image.setRGB((i % (WIDTH * 2)) / 2 + 1, i / (WIDTH * 2), rgb2);
                       }
                   } catch (Exception e) {
                       break;
                   }
               }
               //panelの再描画(内部的にCameraPanel#paintComponent()が呼び出される)
               panel.repaint(1);
           }
        }

        //カメラのフレームを描画するJPanelの定義
        class CameraPanel extends JPanel {
            private static final long serialVersionUID = 1L;
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                // imageが更新されている間はpanelに描画さないようにする
                synchronized (CameraFrame.this) {
                    g.drawImage(image, 0, 0, null);
                }
            }
        }

        public static void main(String[] args) throws IOException {
            // コンスタントラクタ
            final CameraFrame cameraFrame = new CameraFrame();
            
            // 
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    cameraFrame.createAndShowGUI();
                }
            });
            cameraFrame.run();
        }
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?