반응형

오늘은 테서랙트(Tesseract)를 활용한 파이썬(python) OCR 분석을 알아보겠습니다.

파이썬(python)에서 테서랙트(Tesseract)를 사용하기 위해서 pytesseract 패키지를 설치합니다.

또한 이미지 및 open cv를 사용하기 위해서 추가 패키지를 설치합니다.

패키지 설치는 pip 명령어를 사용하거나, 파이참에서 패키지를 바로 설치할 수 있습니다.

pip install pillow 
pip install pytesseract 
pip install opencv-python

정상적으로 패키지가 설치되면 import를 사용해서 패키지를 로드할 수 있습니다.

지난 시간에 사용한 영문 이미지를 동일하게 OCR을 적용하겠습니다.

먼저 tesseract_cmd에 테서랙트(Tesseract) 경로를 선언해주세요.

Image 클래스를 사용해서 영어 이미지를 로드합니다.

마지막으로 image_to_string 함수를 사용해서 영어 문자를 추출합니다.

pytesseract.pytesseract.tesseract_cmd = r'C:\Program Files\Tesseract-OCR\tesseract'
img = Image.open(r'd:\en.jpg')
print(pytesseract.image_to_string(img))

tesseract_cmd 경로가 틀릴 경우 경로를 찾을 수 없다는 오류를 확인할 수 있습니다.

정확하게 테서랙트(Tesseract)가 설치된 경로를 입력해주세요.

실행 결과 출력 창에 정상적으로 영어 텍스트 추출 정보를 확인할 수 있습니다.

한글 텍스트를 추출하기 위해서는 lang를 사용해서 옵션을 추가합니다.

img2 = Image.open(r'd:\kor.jpg')
print(pytesseract.image_to_string(img2, lang='kor'))

pytesseract는 다양한 옵션을 사용해서 테서랙트(Tesseract)를 제어할 수 있습니다.

https://pypi.org/project/pytesseract/

 

pytesseract

Python-tesseract is a python wrapper for Google's Tesseract-OCR

pypi.org

한글 텍스트도 정확하게 추출됩니다.

OCR은 다양한 이미지 정보를 사용하기 때문에 눈으로 이미지를 확인하거나, 이미지를 변경할 수 있어야 합니다.

파이썬(python)에서는 opencv를 사용해서 이미지를 출력하거나, 이미지 프로세싱을 적용할 수 있습니다.

이미지를 확인하기 위해서 cv2 클래스를 사용해서 이미지를 출력할 수 있습니다.

imread 함수는 이미지를 로드해서 객체에 저장할 수 있습니다.

또한 다양한 옵션을 사용해서 이미지 로드 시점에 기본 색상 변경이 가능합니다.

cv2.IMREAD_UNCHANGED 원본 이미지 사용
cv2.IMREAD_GRAYSCALE 1개 채널 그레이스케일 사용
cv2.IMREAD_COLOR 3개 채널, BGR 이미지 사용
cv2.IMREAD_ANYDEPTH 선택 이미지에 따라 정밀도를 16/32비트, 8비트로 적용
cv2.IMREAD_ANYCOLOR 3개 채널, 색상 이미지 사용
cv2.IMREAD_REDUCED_GRAYSCALE_2 1개 채널, 1/2 크기, 그레이스케일 적용
cv2.IMREAD_REDUCED_GRAYSCALE_4 1개 채널, 1/4 크기, 그레이스케일 적용
cv2.IMREAD_REDUCED_GRAYSCALE_8 1개 채널, 1/8 크기, 그레이스케일 적용
cv2.IMREAD_REDUCED_COLOR_2 3개 채널, 1/2크기, BGR 이미지 사용
cv2.IMREAD_REDUCED_COLOR_4 3개 채널, 1/4크기, BGR 이미지 사용
cv2.IMREAD_REDUCED_COLOR_8 3개 채널, 1/8크기, BGR 이미지 사용

imshow 함수를 사용해서 이미지를 모니터 화면에 출력하고 waitKey 함수를 사용해서 키 입력할 때까지 무한 대기합니다.

실행 결과 로드된 이미지가 화면에 출력됩니다.

opencv는 다양한 이미지를 변환할 수 있어 OCR 텍스트 추출 시 인식률을 높일 수 있습니다.

파이썬(python)은 테서랙트(Tesseract) 래퍼 클래스(Wrapper Class) pytesseract와 opencv를 사용해서 다양한 이미지 텍스트 추출을 쉽게 진행할 수 있어 매우 편리합니다

다음 시간에는 opencv를 사용해서 이미지를 변경하는 방법을 알아보겠습니다.

감사합니다.

https://believecom.tistory.com/726

 

[python] 파이썬 Tesseract OCR 활용 설치하기

오늘은 파이썬(python)을 활용해서 OCR를 사용하는 방법을 알아보겠습니다. OCR(optical character recognition)은 이미지에 포함된 텍스트 정보를 추출하는 기술입니다. 요즘은 텍스트 정보 추출 기술이 발

believecom.tistory.com

반응형
반응형

오늘은 파이썬(python)을 활용해서 OCR를 사용하는 방법을 알아보겠습니다.

OCR(optical character recognition)은 이미지에 포함된 텍스트 정보를 추출하는 기술입니다.

요즘은 텍스트 정보 추출 기술이 발전되어 AI 기반으로 많이 사용됩니다.

수많은 OCR 제품이 있지만, 무료 사용할 수 있으면서 활용도가 높은 테서랙트(Tesseract)를 사용해서 이미지 텍스트를 추출해보겠습니다.

이번 시간에는 테서랙트(Tesseract)를 설치해서 이미지 텍스트를 추출하는 방법을 알아보겠습니다.

먼저 아래 사이트에서 설치 파일을 다운로드해주세요.

https://github.com/UB-Mannheim/tesseract/wiki

 

UB-Mannheim/tesseract

Tesseract Open Source OCR Engine (main repository) - UB-Mannheim/tesseract

github.com

전 Windows 기준으로 v5.0.0 64bit 버전을 다운로드하였습니다.

설치 파일을 더블 클릭해서 실행해주세요.

별도 선택 필요 없이 "Next" 버튼을 클릭하면 바로 설치됩니다.

설치 경로는 기본적으로 "Program Files" 아래 "Tesseract-OCR" 폴더에 설치됩니다.

먼저 이 경로를 복사해주세요.

이제 테서랙트( Tesseract ) 명령어를 사용하기 위해서 시스템에서 환경 변수를 등록해주세요.

복사한 경로를 시스템 환경 변수 "PATH"에 추가해주세요.

정상적으로 추가되면 "tesseract" 명령어로 내용을 확인할 수 있습니다.

이제 OCR을 테스트하기 위해서 영어 이미지를 만들었습니다.

테서랙트(Tesseract) 데이터 부분을 캡처했습니다.

테서랙트(Tesseract) 기본 명령어는 stdout -l를 사용해서 언어를 선택할 수 있습니다.

tesseract [경로] stdout -l [언어]

tesseract d:\en.jpg stdout -l eng

텍스트 추출 결과 영어이라서 그런지 대부분 텍스트를 정상적으로 추출했습니다.

이번에는 한글을 추출하기 위해서 옵션을 "kor"로 변경했습니다.

이미지도 한글이 포함된 이미지를 생성했습니다.

영어와 동일하게 이미지 경로와 언어만 변경했습니다.

그런데 "Failed loading language 'kor' " 오류가 발생하면서 텍스트 추출이 안됩니다.

확인해보면 테서랙트(Tesseract)는 tessdata 폴더에 포함된 언어 정보를 확인해서 텍스트를 추출하는데 'kor' traineddata가 없어서 발생한 문제입니다.

아래 사이트에서 테서랙트(Tesseract)다양한 언어 정보를 확인할 수 있습니다.

https://github.com/tesseract-ocr/tessdata

 

tesseract-ocr/tessdata

Trained models with support for legacy and LSTM OCR engine - tesseract-ocr/tessdata

github.com

아래쪽으로 스크롤하면 "kor.traineddata" 파일을 확인할 수 있습니다.

클릭하고 다운로드해주세요.

테서랙트(Tesseract) "tessdata" 폴더에 다운로드된 kor 파일을 복사합니다.

한글 텍스트를 추출하기 위해서 다시 명령어를 입력하면 정상적으로 한글 텍스트를 추출하는 것을 확인할 수 있습니다.

이번에는 한글과 영어를 한 번에 확인할 수 있는 이미지를 만들었습니다.

명령어는 기존과 동일하지만 언어 부분에 "kor+eng"로 변경했습니다.

tesseract [경로] stdout -l [언어]

tesseract d:\keng.jpg stdout -l kor+eng
tesseract d:\keng.jpg stdout -l kor+eng > keng.txt

정상적으로 한글, 영어 모두 추출되는 것을 확인할 수 있습니다.

한글, 영어를 분리해서 사용할 경우가 가장 추출 내용이 정확합니다.

한글, 영어를 혼합해서 사용할 경우 유실되는 정보가 조금씩 존재합니다. 

별도 텍스트 파일로 저장하고 싶다면 ">" 기호를 사용해서 텍스트 파일을 저장할 수 있습니다.

테서랙트(Tesseract)는 다양한 이미지 정보에 포함된 텍스트 정보를 추출할 수 있는 좋은 모듈입니다.

무료 사용도 가능하고 다양한 언어를 추출할 수 있기 때문에 더욱더 편리합니다.

다음 시간에는 테서랙트(tesseract)를 이용한 파이썬(python) 코드를 알아보겠습니다.

감사합니다.

반응형
반응형

개발자는 다양한 정보를 기록하기 위해서 다양한 노트 프로그램을 사용합니다.

대표적으로 OneNote, Notion, Evernote 등이 있습니다.

이중 가장 관심이 높은 프로그램은 무료 라이선스 변경으로 사랑받고 있는 Notion입니다.

기존 Notion은 천 블록만 사용할 수 있는 유료 프로그램이었습니다.

하지만 얼마전부터 무제한 블록 사용할 수 있도록 라이선스를 변경했습니다.

Notion에는 많은 기능이 있지만, 오늘은 Notion에서 강력하게 지원하는 Web Clipper 기능을 알아보겠습니다.

chrome.google.com/webstore/detail/notion-web-clipper/knheggckgoiihginacbkhaalnibhilkk?hl=en

 

Notion Web Clipper

Web Clipper를 이용하면 어떤 웹사이트라도 Notion에 저장할 수 있습니다.

chrome.google.com

Notion Web Clipper 기능은 Chrome, FireFox에서 사용이 가능합니다.

매우 강력하게 Web Page 대부분 정보를 깔끔하게 저장할 수 있어 정말 편리한 기능입니다.

Chrome 기준으로 먼저 Chrome 확장 프로그램을 설치하면 됩니다.

설치 후 확장 프로그램 리스트에서 Chrome 툴바에 고정하면 Notion 아이콘을 확인할 수 있습니다.

저장하기 위한 Web Page에서 Notion 아이콘을 클릭하면 로그인 화면을 확인할 수 있습니다.

한 번 인증 후 동기화를 진행하면 다른 디바이스에서도 바로 사용이 가능합니다.

로그인을 하게 되면 Notion에 저장된 최상위 목록을 확인할 수 있습니다.

Notion Web Clipper 기능은 최상위 목록에만 사용이 가능하며, 하위 목록에는 추가할 수 없습니다.

워크스페이스도 선택이 가능합니다.

추가 대상을 "새로운 링크 데이터베이스"로 선택하면 신규 데이터베이스 리스트가 추가됩니다.

정상적으로 등록되면 리스트에 선택한 Web Page 정보를 확인할 수 있습니다.

URL 속성에 페이지 정보가 저장되고 하단에 전체 글을 확인할 수 있습니다.

Chrome 웹 스토어는 텍스트 기반이 아니기 때문에 하단 문구를 확인할 수 없습니다.

Naver에서 다른 Web Page를 추가하면 URL 정보와 함께 내용이 하단에 저장됩니다.

Notion Web Clipper 기능은 모바일에서도 동일하게 사용이 가능합니다.

모바일은 별도 설치 없이 Chrome 앱에서 동기화를 선택 후 Notion에 보내기를

실행하면 Web Clipper 기능이 실행됩니다.

Chrome 브라우저와 동일하게 모든 기능을 사용할 수 있습니다.

Notion Web Clipper 기능은 Web Page 정보를 데이터 베이스로 저장하고,

검색을 이용해서 빠르게 정보를 확인할 수 있는 좋은 기능입니다.

Notion에 다양한 기능이 있지만 Web Clipper 기능은 꼭 한번 확인해보세요.

감사합니다.

www.notion.so/Web-Clipper-69c78e17c2344c4c902f76fd1713749e

 

Web Clipper

Notion Web Clipper를 사용하면 인터넷의 모든 웹 페이지를 워크스페이스에 저장하고 필요할 때 읽거나 편집할 수 있습니다. 이 기능을 이용하면 원하는 웹 콘텐츠를 모든 워크스페이스나 페이지에

www.notion.so

 

반응형
반응형

지난 시간에 카메라를 사용해서 이미지 뷰에 연결하는 방법을 공부했습니다.

카메라 캡처를 사용해서 이미지를 사용하면 해상도가 떨어지기 때문에 원본이 손실되는 문제가 발생했습니다.

이번 시간에는 원본 이미지 손실을 최소화할 수 있는 이미지 저장 방법에 대해서 알아보겠습니다.

지난 시간에 배운 코틀린을 이용한 카메라 이미지 저장 실행 화면입니다.

원본 이미지 해상도가 많이 떨어지는 것을 확인할 수 있습니다.

해상도를 유지하기 위해서 먼저 촬영된 이미지를 원본 그대로 갤러리에 저장 후 로드하는 형태로 변경해보겠습니다.

카메라 원보 이미지를 저장하기 위해서 먼저 이미지 경로 Uri를 생성합니다.

fun createImageUri(filename:String, mimeType:String):Uri?{
        var values = ContentValues()
        values.put(MediaStore.Images.Media.DISPLAY_NAME,filename)
        values.put(MediaStore.Images.Media.MIME_TYPE, mimeType)
        return contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
    }

ContentValues를 사용해서 이미지 Uri를 생성합니다.

contentResolver는 contentProvider과 비즈니스 로직의 중계자 역할을 담당합니다.

ContentValues는 contentResolver이 사용하는 데이터 정보라고 생각하면 됩니다.

ContentValues에 이미지 이름과 타입을 저장합니다.

카메라를 동작하기 위해서 dispatchTakePictureIntentEx 함수를 추가합니다.

private var photoURI : Uri? = null
    private val REQUEST_CREATE_EX = 3

    private fun dispatchTakePictureIntentEx()
    {
        val timeStamp: String = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date())
        val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
        val takePictureIntent : Intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
        val uri : Uri? =   createImageUri("JPEG_${timeStamp}_", "image/jpg")
        photoURI = uri
        takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
        startActivityForResult(takePictureIntent, REQUEST_CREATE_EX)
    }

전역 경로 photoURI, 이벤트 ID REQUEST_CREATE_EX를 선언합니다.

이전 시간에 선언한 함수와 동일하 구성이기 때문에 Ex를 붙여서 이름을 변경했습니다.

timeStamp를 사용해서 이미지 이름을 시간에 따라서 생성합니다.

CreateimageUri 함수를 호출해서 이미지를 생성하고 카메라를 실행합니다.

fun loadBitmapFromMediaStoreBy(photoUri: Uri) : Bitmap?{
        var image: Bitmap? = null
        try{
            image = if(Build.VERSION.SDK_INT > 27){
                val source: ImageDecoder.Source =
                    ImageDecoder.createSource(this.contentResolver, photoUri)
                ImageDecoder.decodeBitmap(source)

            }else{
                MediaStore.Images.Media.getBitmap(this.contentResolver, photoUri)
            }
        }catch(e:IOException){
            e.printStackTrace()
        }
        return image
    }

생성된 Uri 경로에 이미지를 MediaStore를 사용해서 읽어옵니다.

 btnCamera.setOnClickListener{
                if(checkPermission()){
                    //dispatchTakePictureIntent()
                    dispatchTakePictureIntentEx()
                }
            else{
                    requestPermission()
                }
        }

기존에 연결되어 있던 버튼 이벤트에서 신규로 선언한 dispatchTakePictureIntentEx 함수를 실행합니다.

else if( requestCode == REQUEST_CREATE_EX)
{
    if( photoURI != null)
    {
           val bitmap = loadBitmapFromMediaStoreBy(photoURI!!)
           GImageView.setImageBitmap(bitmap)
           photoURI = null
    }
}

onActivityResult 함수에서 이벤트 ID REQUEST_CREATE_EX를 필터링 후

이미지를 로드하는 loadBitmapFromMediaStoreBy 함수를 호출해서 이미지 뷰에 연결합니다.

카메라 촬영 후 갤러리를 확인하면 카메라 이미지를 확인할 수 있습니다.

원본 이미지를 사용해서 이미지뷰에 연결하면 해상도가 동일한 것을 확인할 수 있습니다.

카메라 이미지 해상도를 원본과 동일하게하기 위해서 별도 저장 후 로드하는 방법을 사용하게 가장 좋은 방법입니다.

이미지 정보가 시간에 따라서 변경되기 때문에 이름을 고정하면 한 개의 사진만 업데이트됩니다.

코틀린을 사용하면 코드가 매우 간결하기 때문에 매우 편리합니다.

객체를 주고받을 때 NULL 존재하기 때문에 ?를 사용하는 부분만 확인하면 어렵지 않은 코드입니다.

감사합니다.

 

반응형
반응형

오늘은 코틀린(Kotlin)을 사용해서 안드로이드 카메라 이벤트 이미지를 이미지 뷰에 출력해보겠습니다.

안드로이드 카메라를 사용하기 위해서 먼저 AndroidMainfest.xml에 속성을 추가해주세요.

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" android:required="true" />

 "required" 속성이 true일 경우는 반드시 카메라 사용 옵션입니다.

경우에 따라서 설정을 변경하면 됩니다.

카메라를 실행하기 위해서 activity_main.xml에 button을 추가합니다.

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnGallery"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Gallery"
            tools:layout_editor_absoluteX="62dp"
            tools:layout_editor_absoluteY="16dp" />

        <Button
            android:id="@+id/btnCamera"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Camera"
            tools:layout_editor_absoluteY="76dp" />
    </LinearLayout>


    <ImageView
        android:id="@+id/GImageView"
        android:layout_width="match_parent"
        android:layout_height="500dp"
        tools:layout_editor_absoluteX="16dp"
        tools:layout_editor_absoluteY="124dp" />

    </LinearLayout>
    

</androidx.constraintlayout.widget.ConstraintLayout>

xml 추가 후 빌드하면 버튼이 정렬되어 출력됩니다.

"CAMERA" 버튼을 클릭하면 카메라를 실행하고, 촬영된 이미지를 하단 이미지 뷰에 추가하겠습니다.

카메라를 사용하기 위해서는 먼저 권한을 승인받아야 합니다.

 private fun requestPermission(){
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE,CAMERA),1)

    }
    private fun checkPermission():Boolean{

        return (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(this,
        Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)

    }
    @Override
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<out String>,
        grantResults: IntArray
    ) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)

        if( requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
            Toast.makeText(this, "권한 설정 OK", Toast.LENGTH_SHORT).show()
        }
        else
        {
            Toast.makeText(this, "권한 허용 안됨", Toast.LENGTH_SHORT).show()
        }
    }

ActivityCompat Class를 사용해서 카메라 사용 권한을 요청합니다.

checkPermission() 함수는 권한 여부를 확인할 수 있습니다.

onRequestPermissionsResult() 함수를 override 후 권한 승인에 따른 이벤트를 확인할 수 있습니다.

즉 권한이 없을 경우 앱 동작을 중단하거나, 메시지를 출력할 수 있습니다.

카메라를 실행하기 위해서 Intent를 실행합니다.

    private val REQUEST_IMAGE_CAPTURE = 2
    private fun dispatchTakePictureIntent() {
        Intent(MediaStore.ACTION_IMAGE_CAPTURE).also { takePictureIntent ->
            takePictureIntent.resolveActivity(packageManager)?.also {
                startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
            }
        }
    }

권한이 승인되면 MediaStore.ACTION_IMAGE_CAPTURE argument를 사용해서 Intent를 실행합니다.

이젠 버튼 이벤트를 연결해서 dispatchTakePictureIntent() 함수를 실행합니다.

btnCamera.setOnClickListener{
                if(checkPermission()){
                    dispatchTakePictureIntent()
                }
            else{
                    requestPermission()
                }
        }

button event에서 checkPermission() 함수를 실행 후 권한이 없다면 권한을 재 요청합니다.

권한 승인 되었다면 카메라를 실행합니다.

정상적으로 카메라 실행 화면을 확인할 수 있습니다.

카메라 촬영 버튼을 클릭하면 이미지가 저장되면서 이벤트가 발생합니다.

이전 시간에 배운 onActivityResult 이벤트를 사용해서 이미지를 저장합니다.

@Override
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if( resultCode == Activity.RESULT_OK) {
            if (requestCode == GALLERY) {
                var ImnageData: Uri? = data?.data
                Toast.makeText(this, ImnageData.toString(), Toast.LENGTH_SHORT).show()
                try {
                    val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, ImnageData)
                    GImageView.setImageBitmap(bitmap)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }
            else if( requestCode == REQUEST_IMAGE_CAPTURE)
            {
                val imageBitmap :Bitmap? = data?.extras?.get("data") as Bitmap
                GImageView.setImageBitmap(imageBitmap)
            }
        }
    }

requestCode가 REQUEST_IMAGE_CAPTURE일 경우 "data" 이미지를 이미지 뷰에 연결할 수 있습니다.

Intent를 사용한 뷰 이벤트는 대부분 onActivityResult를 사용해서 필터링이 가능합니다.

촬영 후 정상적으로 이미지 뷰에 촬영한 사진이 출력됩니다.

일반적인 카메라 이미지를 사용할 경우는 Intent를 사용하면 매우 편리합니다.

하지만, 카메라 기능을 제어할 수 없기 때문에 카메라 기능을 사용할 경우는 별도 뷰를 개발해야 합니다.

감사합니다.

https://developer.android.com/training/camera/photobasics?hl=ko

 

사진 촬영  |  Android 개발자  |  Android Developers

이 과정에서는 기존 카메라 애플리케이션을 사용하여 사진을 캡처하는 방법을 설명합니다. 클라이언트 앱을 실행하는 기기에서 촬영한 하늘 사진을 조합하여 세계 날씨 지도를 만드는 크라우

developer.android.com

 

반응형
반응형

오늘은 코틀린(Kotlin)을 사용해서 캘러리 뷰 이미지 클릭 이벤트에 대해서 알아보겠습니다.

먼저 layout을 변경하기 위해서 mainActivity.xml을 클릭합니다.

 <Button
        android:text="Gallery"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btnGallery"   />

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="500dp"
        android:id="@+id/GImageView" />

갤러리를 호출하기 위한 Button과 선택한 이미지를 출력하기 위한 ImageView를 선언합니다.

ImageView 크기는 원하는 크기로 설정하면 됩니다.

빌드하면 GALLERY BUTTON만 확인할 수 있습니다.

이제 MainActivity에서 버튼 이벤트를 생성해서 갤러리 호출 이벤트 연결이 필요합니다.

    private val GALLERY = 1
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btnGallery.setOnClickListener{
            val intent: Intent = Intent(Intent.ACTION_GET_CONTENT)
            intent.setType("image/*")
            startActivityForResult(intent,GALLERY)
        }

    }

전역 변수로 GALLERY = 1로 정의해주세요.

Intent 갤러리 타입은 1이기 때문에 편하게 사용하기 위해서 정의하는 겁니다.

layout에서 선언한 button에 setOnClickListener 이벤트를 연결합니다.

갤러리는 Intent를 사용해서 호출합니다.

전체 이미지를 확인하기 위해서 "Image/*"로 정의합니다.

코드 작성 후 빌드하면 button 클릭 시 갤러리 화면을 확인할 수 있습니다.

이제 갤러리 이미지에서 이벤트를 연결하겠습니다.

 @Override
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)

        if( resultCode == Activity.RESULT_OK){
            if( requestCode ==  GALLERY)
            {
                var ImnageData: Uri? = data?.data
                Toast.makeText(this,ImnageData.toString(), Toast.LENGTH_SHORT ).show()
                try {
                    val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, ImnageData)
                    GImageView.setImageBitmap(bitmap)
                }
                catch (e:Exception)
                {
                    e.printStackTrace()
                }
            }
        }
    }

onActivityResult 함수를 override 해줍니다.

onActivityResult 함수는 호출된 Activity 이벤트를 확인할 수 있습니다.

resultCode는 Activity 완료 이벤트를 확인할 수 있습니다.

requestCode는 호출 Code를 확인할 수 있습니다.

data에서는 현재 클릭한 Object URL 경로 확인이 가능합니다.

MediaStore 객체를 사용해서 URL 경로에 이미지를 Bitmap로 변경합니다.

마지막으로 Layout에 정의된 GImageView 객체에 setImageBitmap를 사용해서 BitMap을 출력합니다.

출력 결과 선택한 이미지를 ImageView에서 확인할 수 있습니다.

Intent를 사용해서 간단하게 갤러리 이미지를 확인할 수 있지만,

갤러리 뷰를 마음대로 조절할 수 없기 때문에 디바이스 종속적으로 사용만 가능합니다.

상기 기능은 갤러리에서 이미지를 선택할 경우 사용하면 매우 편리합니다.

감사합니다.

 

 

반응형
반응형

파이썬(python)은 배열을 리스트처럼 자유롭게 사용할 수 있는 언어입니다.

기본적으로 '[]'를 사용해서 정의합니다.

숫자, 문자 모두 사용 가능합니다.

a = [1,2,3,4,5,6,7]
b = ['a','b','c','d']
c = ["aa","bb","cc"]

print(a)
print(b)
print(c)

a, b, c 각각 다른 형태로 리스트를 생성할 수 있습니다.

출력 결과 입력된 정보를 모두 확인 할 수 있습니다.

배열 인덱스를 접근하기 위해서는 0 부터 마지막 개수까지 정수를 입력하면 됩니다.

a = [1,2,3,4,5,6,7]
b = ['a','b','c','d']
c = ["aa","bb","cc"]

print(a)
print(a[0])
print(a[1])
print(a[6])
print(a[-1])

파이썬은 인덱스 값이 -1일 경우 마지막 배열 위치 정보를 확인할 수 있습니다.

a배열의 크기는 7이기 때문에 6이 최대 크기이며, -1을 입력하면 최대 크기인 인덱스 6으로 접근합니다.

출력 결과 마지막 인덱스 크기 값이 같은 것을 확인할 수 있습니다.

 

파이썬은 배열형을 자유롭게 사용이 가능합니다.

a 배열은 정수와 문자를 동시에 사용이 가능합니다.

a = [1,2,'a','b']
b = [1,2,['a','b','c']]
print(a)
print(a[3])
print(a[-1])

print(b)
print(b[1])
print(b[-1])

b배열은 배열 안에 다른 배열도 선언이 가능합니다.

b배열 인덱스 0, 1은 정수 1,2이지만 3번째 인덱스는 문자열 배열입니다.

출력 결과 정수, 문자열, 문자열 배열 모두 확인이 가능합니다.

 

파이썬은 리스트 연산이 가능합니다.

a = [1,2,'a','b']
b = [1,2,['a','b','c']]

print(a + a)
print(a * 2)
print(b * 3)

연산자를 사용해서 리스트를 변경할 수 있습니다.

연산자를 사용하면 기존 리스트 크기가 변경되면서 증가분만큼 리스트가 변경됩니다.

 

선언된 리스트는 다양한 메서드를 사용해서 변경이 가능합니다.

a = [1,2,'a','b']
b = [1,2,['a','b','c']]

print(len(a))
print(a)
print(a.append('a'))
print(a)
del a[-1]
print(a)
a.reverse()
print(a)
a.insert(0,10)
print(a)

리스트 크기를 확인하기 위해서는 len, count를 사용하면 전체 크기를 확인할 수 있습니다.

append 메서드를 사용하면 마지막 인덱스에 요소를 추가할 수 있습니다.

del, remove 메소드를 사용하면 선언된 인덱스 정보를 삭제할 수 있습니다.

reverse 메서드는 배열의 위치를 반대로 변경해줍니다.

마지막으로 insert는 선택 인덱스에 값을 변경할 수 있습니다.

파이썬은 배열을 리스트처럼 자유롭게 사용할 수 있어 다양한 계산이 가능합니다.

리스트는 개발에서 가장 많이 사용되는 요소이기 때문에 꼭 사용법을 익혀주세요.

감사합니다.

반응형
반응형

오늘은 리눅스(Linux) 환경에서 IP 주소를 확인하는 방법을 알아보겠습니다.

리눅스에서 IP를 확인하는 방법은 3가지 정도 있습니다.

 

첫 번째

hostname -I(대문자 I 입니다)

설정된 IP 주소를 바로 확인할 수 있습니다.

 

두 번째

ifconfig

처음 설치 상태에서는 ifconfig 명령어가 없다고 오류를 출력합니다.

ifconfig를 사용하기 위해서는 net-tools 설치가 필요합니다.

sudo apt-get install net-tools

상기 명령어를 사용해서 net-tools를 설치해주세요.

설치 후 ifconfig를 실행하면 IP 정보, netmask, broadcast 등 다양한 정보를 확인할 수 있습니다.

세 번째

ip addr show

추가적인 다양한 정보를 확인할 수 있습니다.

hostname -I, ifconfig, ip addr show 3가지 명령어를 사용해서 IP 정보를 확인할 수 있습니다.

IP 정보는 서버 개발 시 꼭 필요한 정보이기 때문에 명령어를 꼭 숙지해주세요.

감사합니다.

반응형
반응형

파이썬(python)은 문자열을 자유롭게 사용할 수 있습니다.

문자열은 배열로 저장하기 때문에 사용하기 더욱더 편리합니다.

파이썬(python) 문자열을 사용하기 위해서는 큰따옴표( " )와 작은따옴표( ' )를 사용합니다.

a = "파이썬 문자열 시작합니다."
b = '파이썬 문자열 시작합니다.'

print(a)
print(b)

이번에는 지난 시간에 설치한 파이참을 사용해서 빌드하겠습니다.

a, b 변수에 문자열을 할당합니다.

출력은 print() 함수를 사용합니다.

출력 결과 동일한 내용 텍스트를 확인할 수 있습니다.

텍스트 선언 시 큰따옴표와 작은따옴표를 같이 사용할 없습니다.

시작한 문자열과 마지막 문자열이 동일해야 오류가 없습니다.

 

파이썬 이스케이프 코드 사용법

a = "이스케이프 코드 라인 피드 \n"
b = '이스케이프 코드 캐리지 리턴 \r'
c = '이스케이프 코드 탭 \t'
d = "이스케이프 코드 작은 따옴표 \'"
e = "이스케이프 코드 큰 따옴표 \""
f = "이스케이프 코드 백슬래시 \\"

print(a)
print(b)
print(c)
print(d)
print(e)
print(f)

파이썬도 다른 언어와 동일하게 문자열 사용 시 이스케이프 코드를 사용해서 특수 문자열을 추가할 수 있습니다.

이스케이프 코드는 라인피드, 캐리지 리턴, 탭, 작은따옴표, 큰 따옴표, 백 슬래시 등을 사용할 수 있습니다.

 

파이썬 문자열 배열 사용법

파이썬은 문자열을 선언하면 배열형태로 저장되어 인덱싱에 따른 위치 정보를 바로 확인할 수 있습니다.

a = "문자열 배열"
b = "python string array"

print(a[0])
print(a[4])

print(b[0])
print(b[5])

영문과 한글 모두 배열로 저장되며, 좋은 점은 유니코드 상관없이 자동으로 문자열을 변형되어 사용이 가능합니다.

한글 2byte, 영문 1byte 구분 없이 배열에 순서대로 저장되기 때문에 초보자가 사용하기 매우 편리합니다.

설정한 인덱스에 따른 위치 문자가 출력됩니다.

배열 크기 보다 클 경우는 오류가 발생합니다.

인덱스는 배열이기 때문에 0부터 시작합니다.

 

파이썬 문자열 연산자 사용법

파이썬은 + 연산자를 사용해서 문자열을 붙일 수 있습니다.

a = "문자열 배열"
b = "python string array"
c = a + "문자열 추가"
f = a * 10

d = a + b

print(d)
print(c)
print(f)

a, b 선언된 문자열을 + 연산자를 사용해서 d에 저장이 가능합니다.

파이썬에서는 '*' 연산자를 사용해서 문자열 복사가 가능합니다.

출력 결과 문자열을 붙어 있는 것을 확인할 수 있습니다.

a 변수를 10 복사한 내용도 확인이 가능합니다.

문자열을 직관적으로 사용할 수 있어 정말 편리합니다.

 

파이썬 문자열 메서드 사용법

파이썬에서는 문자열을 선언하면 객체로 인식하면 다양한 메서드를 사용할 수 있습니다.

a = "문자열 배열"
b = "python string array"
c = "문자열1|문자열2|문자열3"

print(len(a))
print(a.find('배'))
print(a.index("배"))
print(b.isupper())
print(a.rfind('배'))
print(c.split('|'))

a문자열에 "."을 사용하면 메서드를 확인할 수 있습니다.

다양한 메소드를 사용해서 문자열 정보를 확인할 수 있습니다.

문자열 메소드 중에서 split를 사용하면 구분자를 확인해서 배열 형태로 문자열이 저장됩니다.

파이썬은 문자열을 직관적으로 변경하거나, 연산할 수 있어 사용하기 매우 편리합니다.

decode(), encode()를 사용해서 문자열 인코딩도 가능하고, 바이트 배열에 따른 문자열 출력도 가능합니다.

쉽게 문자열을 접근할 수 있어 코드 내용이 많아 질 경우 오류를 최소화할 수 있습니다.

문자열은 매우 중요한 내용이기 때문에 꼭 많이 코딩해보세요.

감사합니다.

반응형
반응형

 파이썬(python)에서도 다양한 자료형을 사용할 수 있습니다.

오늘은 자료형 기본인 숫자에 대해서 알아보겠습니다.

파이썬(Python)은 기본적으로 바로 숫자를 사용해서 연산이 가능합니다.

일반적으로 컴파일을 진행하기 위해서는 변수를 사용해서 숫자를 대입하지만 파이썬에서 바로 사용이 가능합니다

0
>>> 1 + 1
2
>>> 1 - 1
0
>>> 2 * 2
4
>>> 4 * 5
20
>>> 100 / 5
20.0
>>> 100 % 5
0
>>>

 숫자와 연산자를 입력하면 바로 결과를 확인할 수 있습니다.

일반적인 연산자 및 특수 연산자도 사용이 가능합니다.

>>> a = True
>>> b = False
>>> a = true
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'true' is not defined
>>> b = false
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'false' is not defined
>>>

불린 타입으로 True, False 사용이 가능합니다.

단 정확하게 True, False를 입력해야 합니다.

소문자로만 사용할 경우 오류가 출력됩니다

>>> a = 14
>>> b = -3
>>> c = 4.56
>>> a
14
>>> b
-3
>>> c
4.56
>>>

숫자, 정수 모두 변수를 사용할 수 있습니다.

변수 선언은 바로 '='을 사용해서 입력하면 됩니다.

타입에 따라서 자동적으로 변하기 때문에 별도 변환이 필요 없습니다.

>>> 2 ** 5
32
>>> 5 << 1
10
>>> 5 >> 1
2
>>> 1 & 3
1
>>> 1 | 3
3
>>> 1 ^ 4
5
>>>

다양한 연산자를 사용해서 연산이 가능합니다.

'**'을 사용할 경우 제곱을 바로 확인할 수 있습니다.

비트 시프트 및 논리 연산도 바로 가능합니다.

>>> a = 10
>>> b = 20
>>> c = 30
>>> a > b
False
>>> a == b
False
>>> c != a
True
>>>

변수를 사용해서 숫자를 대입하면 연산자를 사용해서 참, 거짓을 확인할 수 있습니다.

0
>>> a = 4.56
>>> a
4.56
>>> int(a)
4
>>> float(a)
4.56
>>>

마지막으로 정확한 숫자를 확인하기 위해서는 타입명을 입력하고 변수를 넣으면 변경됩니다.

int(변수), float(변수) int형일 경우 소수점이 빠진 정수를 확인할 수 있습니다.

파이썬(Python)은 다양한 자료형 숫자와 연산자를 즉시 사용할 수 있어 빠른 연산이 가능합니다.

일반적인 컴파일 언어에서는 모든 내용을 등록하고 대기해야 하는 단점이 있지만, 파이썬은 이런 부분이 없기 때문에 직관적으로 다양한 분야에 사용이 가능합니다.

감사합니다.

반응형

+ Recent posts