Color detection using Android openCV(안드로이드 OpenCV로 특정 색깔 인식)

※이 프로그램은 OpenCV의 예제파일인 OpenCV Sample - color-blob-detection을 수정한 자료임을 알립니다.


1.먼저 자신이 찾고자 하는 색깔의 Hsv를 알아내야 합니다. 만약 자신이 찾는 색깔의 Hsv를 모르는 경우 해당 색깔의 RGB를 Hsv로 변환하는 사이트를 이용합니다.

http://www.rapidtables.com/convert/color/rgb-to-hsv.htm




위의 RGB 색상 변환으로 나오는 HSV의 값을 아래와 같이 입력하시면 되겠습니다.

new Scalar(235, 75.2, 45.9, 0.0);


위에서 처리한 값을 이제 아래의 onCameraViewStarted() 함수에 입력해주시면 프로그램이 실행하자마자 해당 색상을 검출하는 것을 확인하실 수 있습니다.


ColorBlobDetectionActivity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void onCameraViewStarted(int width, int height) {
        mRgba = new Mat(height, width, CvType.CV_8UC4);
        mDetector = new ColorBlobDetector();
        mSpectrum = new Mat();
        mBlobColorRgba = new Scalar(255);
        SPECTRUM_SIZE = new Size(200, 64);
        CONTOUR_COLOR = new Scalar(255,0,0,255);
        
        
        mBlobColorHsv = new Scalar(235, 75.2, 45.9, 0.0);
        mDetector.setHsvColor(mBlobColorHsv);
        mIsColorSelected = true;
        
    }


300x250

Use front camera with OpenCV 2.4.9 for android(안드로이드 OpenCV에서 전면카메라 적용 방법)

 굳게 마음을 먹고 OpenCV를 사용하여 프로그래밍을 해보려고 하는데 SurfaceView를 통해 전면 카메라를 사용하는 방법과 다른 방법을 쓰는 것 같아 찾아보니 쉽지가 않더군요.


그래서 직접 OpenCV 라이브러리를 찾아보면서 적용방법을 찾아본 결과 다음과 같은 결과를 얻을 수 있었습니다.

안드로이드용 OpenCV에서 아래의 클래스가 카메라를 담당하는 것으로 보였습니다.


private CameraBridgeViewBase mOpenCvCameraView;

위 클래스를 이것 저것 적용하다보니 사용법을 찾아낼 수 있었습니다.

아래의 코드와 같이 onCreate()에서 굵게 표시한 부분을 코드에 삽입하면 OpenCV가 전면카메라를 사용하는 것을 확인하실 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
 
        setContentView(R.layout.color_blob_detection_surface_view);
 
        mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.color_blob_detection_activity_surface_view);
        mOpenCvCameraView.disableView();
        mOpenCvCameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT);
        mOpenCvCameraView.setCvCameraViewListener(this);
    }



300x250

블루투스를 통해 이미지를 바이트로 전송하기

 대부분의 안드로이드 폰에는 블루투스가 기본적으로 내장되어 있습니다. 블루투스 기능을 활용하면 굳이 인터넷이나 기지국을 거치지 않고도 안드로이드 기기간에 파일 전송이 가능하지요.

 이번 포스팅에서는 간단하게 다른 안드로이드 폰으로 사진을 전송하는 방법에 대해 알아보겠습니다.


 시작하기에 앞서 아래에 있는 블루투스 채팅 프로그램 프로젝트를 다운로드하여 Import 합니다.

 

BluetoothChat (1).zip





 위의 예제는 안드로이드 폰 상호간에 간단한 문자 채팅을 할 수 있는 프로그램입니다. 이 프로젝트에 이미지를 전송할 수 있는 기능을 넣어보도록 하겠습니다.


먼저 AndroidManifest.xml 파일에 다음과 같은 퍼미션을 추가 해줍니다.

1
2
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.BLUETOOTH" />


다음으로 메인 레이아웃인 main.xml에 그림을 띄울 ImageView와 그림을 전송하기 위한 Button을 다음과 같이 추가합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <ListView android:id="@+id/in"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:stackFromBottom="true"
        android:transcriptMode="alwaysScroll"
        android:layout_weight="1"
    />
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >
 
        <ImageView
            android:id="@+id/getimage"
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:src="@drawable/app_icon"
            android:scaleType="centerInside"
            />
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
 
            <EditText
                android:id="@+id/edit_text_out"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:layout_weight="1" >
 
                <requestFocus />
            </EditText>
 
            <Button
                android:id="@+id/button_send"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/send" />
 
            <Button
                android:id="@+id/button_image"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/send_image" />
        </LinearLayout>
 
    </LinearLayout>
 
</LinearLayout>
 



다음으로 BluetoothChat.java를 수정해 보도록 하겠습니다.

먼저 추가된 Button과 ImageView에 대한 함수를 생성합니다.
1
2
    private Button mSendImage;
    private ImageView iv;


다음으로 setupChat() 함수 내에 다음과 같이 추가합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    private void setupChat() {
        
        ............
    
        iv = (ImageView)findViewById(R.id.getimage);
        mSendImage = (Button) findViewById(R.id.button_image);
        mSendImage.setOnClickListener(new OnClickListener(){
 
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_PICK,
                                               android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
                startActivityForResult(intent,10);
            }
            
        });
    }


위에서 보는 것과 같이 이미지 갤러리를 Intent를 통해 불러오는 것을 볼 수 있습니다.

Intent를 통해 선택된 사진은 onActivityResult() 함수를 통해 얻을 수 있습니다.


onActivityResult() 함수에 다음과 같이 값을 추가합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        
        ............
        
        switch (requestCode) {
            
            ............
            
            case 10:
            if(resultCode==RESULT_OK && data != null){
                try {
                    Uri selectedImage = data.getData();
                Bitmap bp = Images.Media.getBitmap(this.getContentResolver(), selectedImage);
                    
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                bp.compress(CompressFormat.JPEG, 80, baos);
                byte[] imageByte = baos.toByteArray();
                
                iv.setImageBitmap(BitmapFactory.decodeByteArray(imageByte, 0, imageByte.length));
 
                if(mChatService.getState() == BluetoothChatService.STATE_CONNECTED){                        
                    int len;
                    final int size = 512;
                    byte[] sendByte = new byte[size];
                    ByteArrayInputStream bais = new ByteArrayInputStream(imageByte);
                    mConversationArrayAdapter.add("이미지 전송을 시작합니다.");
    
                        
                    sendByte[0] = 6;
                    sendByte[1] = 26;
                    sendByte[2] = 18;
                    mChatService.write(sendByte);
                    while( (len=bais.read(sendByte)) != -1){                            
                        if(len<512){
                            byte[] EOF = new byte[len];
                            for(int eof=0 ; eof<EOF.length; eof++){
                                EOF[eof] = sendByte[eof];
                            }
                            mChatService.write(EOF);
                            
                        }else{
                            mChatService.write(sendByte);
                        }
                    }
                    
                    sendByte[0] = 26;
                    sendByte[1] = 6;
                    sendByte[2] = 18;
                    mChatService.write(sendByte);
                        
                    mConversationArrayAdapter.add("이미지 전송이 완료되었습니다!");
                    mConversationArrayAdapter.add("Image Size : " + imageByte.length);
                }
                    
            } catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
           }
           break;
     }
    }



마지막으로 Handler를 통해 전송된 사진의 값을 수정하는 부분을 다음과 같이 수정해 줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
....
    boolean imageTransfer = false;
    boolean imageTransferW = false;
    ByteArrayOutputStream ReceiveImage;
 
    // The Handler that gets information back from the BluetoothChatService
    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case MESSAGE_STATE_CHANGE:
                if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                switch (msg.arg1) {
                case BluetoothChatService.STATE_CONNECTED:
                    mTitle.setText(R.string.title_connected_to);
                    mTitle.append(mConnectedDeviceName);
                    mConversationArrayAdapter.clear();
                    break;
                case BluetoothChatService.STATE_CONNECTING:
                    mTitle.setText(R.string.title_connecting);
                    break;
                case BluetoothChatService.STATE_LISTEN:
                case BluetoothChatService.STATE_NONE:
                    mTitle.setText(R.string.title_not_connected);
                    break;
                }
                break;
            case MESSAGE_WRITE:
                byte[] writeBuf = (byte[]) msg.obj;
                String writeMessage = new String(writeBuf);
                mConversationArrayAdapter.add(writeBuf.length+" "+(int)writeBuf[0]
                                                +" "+(int)writeBuf[1]);
                mConversationArrayAdapter.add("나 :  " + writeMessage);
                
                break;
            case MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                // construct a string from the valid bytes in the buffer
                if(msg.arg1 > 2 && readBuf[0]==6 && readBuf[1]==26 && readBuf[2== 18){
                    imageTransfer = true;
                    ReceiveImage = new ByteArrayOutputStream();
                    mConversationArrayAdapter.add("Image Transfer Start!");
                    break;
                }
                
                if(msg.arg1 > 2 && readBuf[0]==26 && readBuf[1]==6 && readBuf[2== 18){
                    imageTransfer = false;
                    mConversationArrayAdapter.add("Image Transfer End!");
                    mConversationArrayAdapter.add("Image Size : " + ReceiveImage.size());
                    byte[] getImage = ReceiveImage.toByteArray();
                                        
                    iv.setImageBitmap(BitmapFactory.decodeByteArray(getImage, 0, getImage.length));
                    
                    break;
                }
                
                if(imageTransfer){
                    try {
                        ReceiveImage.write(readBuf);
                        if(readBuf.length==512)
                        mConversationArrayAdapter.add("Size : " + readBuf.length +", "
                                                    +(short)readBuf[0]+", " + (short)readBuf[511]);
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }else{
                    String readMessage = new String(readBuf, 0, msg.arg1);
                    mConversationArrayAdapter.add(mConnectedDeviceName+":  " + readMessage);
                }
                break;
            case MESSAGE_DEVICE_NAME:
                // save the connected device's name
                mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
                Toast.makeText(getApplicationContext(), "Connected to "
                               + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                break;
            case MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
                               Toast.LENGTH_SHORT).show();
                break;
                
            case 6:
                //Toast.makeText(getApplicationContext(), "WTF", Toast.LENGTH_SHORT).show();
                
                break;
            }
        }
    };
....
cs


300x250