Oracle의 Java 1.8의 유료화 정책이 공개됬습니다. 

2019년 부터 Oracle에서 배포하는 Java 1.8 SDK 및 JRE 모든 공개용 패키지를 이용하여 상업 목적의 개발 및 사용에 대한 유료화 정책입니다.


♠ Java의 저작권에 대해

2006년 Sun이 Java를 공식 오픈소스화 했습니다. 현재는 Oracle이 Sun을 인수하였으며 최근에 Java EE까지 오픈소스화 할 계획을 발표했습니다.


♠ Oracle JDK의 대체

https://en.wikipedia.org/wiki/List_of_Java_virtual_machines

해당 사이트를 참조하여 적절한 제품을 찾으시길 바랍니다.

또한 Oracle JDK가 아닌 OpenJDK의 사용을 권해드립니다.


♠ Oracle JDK를 지속적으로 사용하실 분은 다음과 같은 가격을 지불해야 합니다.

=> SE Subscription (Server) :  # core * core factor (oracle core factor table) * # server * 25$/month * 12 months

=> SE Subscription (Desktop) :  # of desktops * 2.50$/month 

또한 여기에서 US Oracle Technology Commercial Price List를 확인 할 수 있습니다.


자바 유료화에 대한 더 자세한 정보는 여기서 확인하세요.




질문 또는 오타나 잘못된 정보가 있는 경우 댓글로 달아주세요!

공감♡ 버튼을 눌러주시면 더욱 유용하고 좋은 포스팅으로 찾아 뵙겠습니다.






이번에는 아두이노끼리 블루투스 통신 하는 방법에 대해 알아보겠습니다.

블루투스 통신을 위해 다음 모듈이 필요합니다.

HC06 모듈입니다.


제원은 다음과 같습니다.

○ 범위 : ~10M 

○ 동작 전원 : 3.6 ~ 6V

○ 사용 전력 : ~30mA

○ 크기 : 36 x 15 mm

○ 기본 통신 속도(Baud rate) : 9600

○ 초기 페어링 비밀번호 : 1234


핀은 다음과 같이 배치합니다.

● VCC : 5V (전원)

● GND : GND (그라운드)

● RX : Digital 2 pin (데이터 수신)

● TX : Digital 3 pin (데이터 송신)


아두이노 스케치에서 시리얼 모니터를 열어서 다음과 같이 명령어를 입력합니다.

☆ AT : 블루투스 통신이 유효한지 확인합니다. (성공시 OK출력)

☆ AT+VERSION : 블루투스 모듈의 버전을 확인합니다.

☆ AT+ROLE=M : 통신 모드를 Master로 변경합니다.

☆ AT+ROLE=S : 통신 모드를 Slave로 변경합니다

☆ AT+BAUD4 : 기본 Baud rate를 변경합니다. (1~8까지)

    1 : 1200 / 2 : 2400 / 3 : 4800 / 4 : 9600 / 5 : 19200 / 6 : 38400 / 7 : 57600 / 8 : 115200

☆ AT+NAMEdevicename : 블루투스 명칭을 변경합니다. (성공시 OKname 출력)

☆ AT+PIN**** : Pin Code(비밀번호)를 변경합니다.(성공시 Oksetpin 출력)

☆ AT+INQ : 주변 블루투스 모듈을 검색합니다.

☆ AT+CLRBAND : 블루투스 연결을 해제합니다.


* 자세한건 여기를 확인하세요.


위 설정을 모두 끝냈다면 다음 코드를 작성합니다.

1. 컴퓨터가 2대 이상 있는 경우 - 각각의 컴퓨터에 아두이노를 연결하고 다음과 같이 작성합니다.

* 스케치 - 라이브러리 포함하기 - SoftwareSerial 을 선택합니다.

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); //블루투스의 Tx, Rx핀을 2번 3번핀으로 설정


void setup() {

  // Baud rate 9600으로 설정

  Serial.begin(9600);

  mySerial.begin(9600);

}


void loop() {

  if (mySerial.available()) { //블루투스에서 넘어온 데이터가 있다면

    Serial.write(mySerial.read()); //시리얼모니터에 데이터를 출력

  }

  if (Serial.available()) {    //시리얼모니터에 입력된 데이터가 있다면

    mySerial.write(Serial.read());  //블루투스를 통해 입력된 데이터 전달

  }

}


2. 컴퓨터가 1대 있는 경우 - Master 및 Slave 모듈을 번갈아가며 작성합니다.

· Master 코드

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); //블루투스의 Tx, Rx핀을 2번 3번핀으로 설정


void setup() {

  Serial.begin(9600);

  mySerial.begin(9600); // baud rate 9600으로 설정

}


void loop() { 

  if (mySerial.available()) { // 넘어온 데이터가 존재하면

    Serial.write(mySerial.read()); // 시리얼에 출력

  }

}


· Slave 코드

#include <SoftwareSerial.h>

SoftwareSerial mySerial(2, 3); //블루투스의 Tx, Rx핀을 2번 3번핀으로 설정

int a= 0;


void setup() {

  Serial.begin(9600);

  mySerial.begin(9600); // baud rate 9600으로 설정

}


void loop() {

  mySerial.println(a); // 블루투스 시리얼에 입력

  a++;

  delay(500);


2.의 실행 화면입니다.





정보가 유익하셨다면 아래 공감버튼 눌러주시면 감사하겠습니다.

질문사항은 댓글로 달아주시면 성의껏 답변해드리겠습니다.




이번 시간에는 OpenCV를 이용하여 관심역영(ROI)을 추출하겠습니다.

관심영역 추출은 문자인식 전처리 기법 중 하나로

인식 할 범위를 대폭 축소시켜 프로그램 전반적인 실행속도를 향상 시키고

인식률 또한 높일 수 있는 전처리 기법입니다.


※ 안드로이드와 OpenCV 연동은 이곳을 참고하세요.

※ SurfaceView와 카메라 연동은 이곳을 참고하세요.


동작 과정

1. SurfaceView에 카메라 화면 출력

2. 캡쳐를 누르면 안드로이드 내부 저장소에 사진이 저장

3. 새로운 액티비티가 실행되며 저장소에 저장된 사진을 불러옴

4. 불러온 사진을 흑백처리, 이진화처리 수행

5. 처리된 사진을 OpenCV 라이브러리 함수로 영역들을 추출해냄

6. 추출된 영역 중 자동차 번호판에 해당하는 영역만 표시

7. 표시된 영역을 따로 결과화면에 출력

8. 출력된 관심영역을 가지고 문자인식 수행



소스코드 입니다.


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
List<MatOfPoint> contours = new ArrayList<>(); 
 
Mat hierarchy = new Mat();
 
Imgproc.findContours(imageCny1, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
 
 
for(int idx = 0; idx >= 0; idx = (int) hierarchy.get(0, idx)[0]) {
 
MatOfPoint matOfPoint = contours.get(idx);
 
Rect rect = Imgproc.boundingRect(matOfPoint);
 
if(rect.width < 30 || rect.height < 30 || rect.width <= rect.height || rect.x < 20 || rect.y < 20
 
|| rect.width <= rect.height * 3 || rect.width >= rect.height * 6continue// 사각형 크기에 따라 출력 여부 결정
 
 
 
// ROI 출력
 
Bitmap roi = Bitmap.createBitmap(myBitmap, (int)rect.tl().x, (int)rect.tl().y, rect.width, rect.height);
 
ImageView imageView1 = (ImageView)findViewById(R.id.image_result_ROI);
 
imageView1.setImageBitmap(roi);
 
}
 
 
image1= Bitmap.createBitmap(img1.cols(), img1.rows(), Bitmap.Config.ARGB_8888);
 
Utils.matToBitmap(img1, image1); // Mat to Bitmap
 
 
imageView = (ImageView)findViewById(R.id.image_result);
 
imageView.setImageBitmap(image1);
 
}
cs



실행화면 입니다.


  





정보가 유익하셨다면 아래 공감버튼 눌러주시면 감사하겠습니다.

질문사항은 댓글로 달아주시면 성의껏 답변해드리겠습니다.







안드로이드에 OpenCV를 설치하는 방법에 대해 알아봅시다.

아래에 링크에 들어가서 OpenCV 3.4.3 android sdk를 다운받고 적절한 폴더에 설치합니다.

https://github.com/opencv/opencv/releases

OpenCV를 설치할 프로젝트를 열고

File-New-Import Module을 선택합니다.



방금 설치한 OpenCV 폴더로 이동해서

sdk/java를 선택하고 OK를 눌러줍니다.

제대로 된 폴더를 선택했다면 OpenCV라는 모듈명이 나옵니다.



모듈을 추가하고 app/build.gradle에 들어가서 맨 아래 프로젝트 추가 코드를 입력합니다.


아래는 이미지파일을 비트맵으로 받아와 흑백 및 에지검출 소스코드입니다.


File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "이미지 파일 경로.png"); // 파일 불러오기

if(file.exists()){ // 파일이 존재한다면

    Bitmap myBitmap = BitmapFactory.decodeFile(file.getAbsolutePath()); // 비트맵 생성


    Bitmap image1;

    OpenCVLoader.initDebug(); // 이 코드를 선언해주지않으면 컴파일 에러 발생


    Mat img1=new Mat();

    Utils.bitmapToMat(myBitmap ,img1);

    Mat imageGray1 = new Mat();

    Mat imageCny1 = new Mat();


    //Imgproc.cvtColor(img1, imageGray1, Imgproc.COLOR_BGR2GRAY); // GrayScale


    //Imgproc.Canny(imageGray1, imageCny1, 10, 100, 3, true); // Canny Edge 검출


    //Imgproc.threshold(imageGray1, imageCny1, 150, 255, Imgproc.THRESH_BINARY); //Binary


    image1= Bitmap.createBitmap(imageCny1.cols(), imageCny1.rows(), Bitmap.Config.ARGB_8888); // 비트맵 생성

    Utils.matToBitmap(imageCny1, image1); // Mat을 비트맵으로 변환


    imageView = (ImageView)findViewById(R.id.image_result);

    imageView.setImageBitmap(image1); // 이미지 뷰에 비트맵 출력

}





정보가 유익하셨다면 아래 공감버튼 눌러주시면 감사하겠습니다.

질문사항은 댓글로 달아주시면 성의껏 답변해드리겠습니다.




이전 시간에 트리에 대해 공부했습니다. (참고 : 자료구조 트리)

이번 시간에는 이진 탐색 트리에 대해 공부해보겠습니다.


♪ 이진 탐색 트리(Binary Search Tree) : 노드기반(Node-Based) 이진 트리 자료구조입니다.


♪ 특징(Properties) 

좌측 하위 트리(Left Subtree)의 노드들은 상위 노드보다 작거나 같은 값입니다.

우측 하위 트리(Right Subtree)의 노드들은 상위 노드보다 큰 값입니다.

좌측 및 우측 하위트리 역시 이진 탐색 트리입니다. (하위트리의 하위트리들도 모두 위 특징에 해당합니다)


♪ 탐색(Search) 

☞ 탐색의 시작은 루트 노드(Root Node)에서 시작합니다. 만약 탐색하려는 값이 루트 노드의 값이라면 루트 노드의 값을 반환합니다.

☞ 만약 탐색하려는 값이 루트 노드의 값보다 작다면 좌측 하위 트리로 이동해서 탐색을 반복합니다.

☞ 만약 탐색하려는 값이 루트 노드의 값보다 크다면 우측 하위 트리로 이동해서 탐색을 반복합니다.


# 탐색 - 소스코드(C/C++)

struct node* search(struct node* root, int key) // 키 값 : 탐색하려는 값

{

if (root == NULL || root->key == key) // 루트 노드가 없거나 루트 노드의 값이 키 값인 경우

return root; // 루트 노드 반환

    

if (root->key < key) // 키 값이 루트 노드의 값보다 크다면

return search(root->right, key); // 우측 하위 트리 탐색

 

// 키 값이 더 작다면

return search(root->left, key); // 좌측 하위 트리 탐색

}



♪ 삽입(Insertion) : 새로운 노드는 항상 잎(Leaf) 노드에서 발생합니다.

☞ 루트 노드에서 탐색을 시작합니다. 만약 루트 노드가 없다면 노드를 삽입합니다.

☞ 잎(Leaf) 노드를 만날 때 까지 탐색을 시작합니다.

☞ 잎(Leaf) 노드를 만났다면 새로운 노드를 삽입합니다.(새 노드 값이 작다면 좌측, 크다면 우측)


# 삽입 - 소스코드(C/C++)

struct node *newNode(int item) // 새로운 노드 생성 함수

{

    struct node *temp =  (struct node *)malloc(sizeof(struct node)); // 새로운 노드를 동적할당

    temp->key = item; // 키 값을 설정

    temp->left = temp->right = NULL; // 좌측 및 우측 노드 null로 초기화

    return temp;

}

  

struct node* insert(struct node* node, int key) // 삽입 함수; node는 root노드, key는 삽입하려는 값

{

    if (node == NULL) return newNode(key); // 루트 노드가 없다면 바로 삽입

 

    if (key < node->key) // 새 노드가 루트노드 값보다 작다면

        node->left  = insert(node->left, key); // 좌측 서브트리로 이동해서 반복

    else if (key > node->key) // 새 노드가 루트노드 값보다 크다면

        node->right = insert(node->right, key); // 우측 서브트리로 이동해서 반복

 

    return node;

}



♪ 삭제(Delete) :  설명은 소스코드 주석으로 대체합니다.


# 삭제 - 소스코드(C/C++)

struct node * minValueNode(struct node* node) // 가장 작은 노드 반환 함수

{

    struct node* current = node; // 루트 노드 복사

 

    while (current->left != NULL) // 좌측 서브트리가 없을 때 까지 반복

        current = current->left;

 

    return current; 

}

 

struct node* deleteNode(struct node* root, int key) // 삭제 함수

{

    if (root == NULL) return root; // 루트 노드 null이라면 루트 노드 반환

 

    if (key < root->key) // 삭제하려는 노드의 값이 루트노드의 값보다 작다면

        root->left = deleteNode(root->left, key); // 좌측 서브트리로 이동해서 반복

 

    else if (key > root->key) // 크다면

        root->right = deleteNode(root->right, key); // 우측 서브트리로 이동해서 반복


    else // 삭제하려는 노드가 루트 노드

    {

        if (root->left == NULL) // 좌측 서브트리가 없는 경우

        {

            struct node *temp = root->right; // 우측 서브트리 복사

            free(root); // 루트 노드 삭제

            return temp; // 우측 서브트리 반환

        }

        else if (root->right == NULL) // 우측 서브트리가 없는 경우

        {

            struct node *temp = root->left; // 좌측 서브트리 복사

            free(root); // 루트 노드 삭제

            return temp; // 좌측 서브트리 반환

        }

 

        // 좌, 우측 서브트리 모두 있을 경우

        struct node* temp = minValueNode(root->right); // 우측 서브트리 중 가장 작은 값 복사

 

        root->key = temp->key; // 복사 한 값을 루트 노드에 복사

 

        root->right = deleteNode(root->right, temp->key); // 루트의 우측 서브트리 이동해서 반복

    }

    return root;

}





정보가 유익하셨다면 아래 공감버튼 눌러주시면 감사하겠습니다.

질문사항은 댓글로 달아주시면 성의껏 답변해드리겠습니다.


'자료구조, 알고리즘' 카테고리의 다른 글

정렬 알고리즘 종류  (0) 2018.09.12
검색 알고리즘 종류  (2) 2018.09.11
자료구조 그래프(Graph)  (1) 2018.09.06
자료구조 힙(Heap)  (0) 2018.09.05
자료구조 트리(Tree)  (0) 2018.08.30
[자료구조] 큐 QUEUE  (0) 2018.08.19
[자료구조] 스택 STACK  (0) 2018.08.19
[BOJ] 1912 연속합 - 동적계획법 풀이  (0) 2018.08.17

to Top