2023년 3월 7일 화요일

BentoML 사용법 요약

> D:\2023\poop_wrn로 이동


bentoml serve service:svc --port 3010 --reload   # bentoml 서비스 실행
locust --headless -u 100 -r 1000 --run-time 1m
--host http://127.0.0.1:3010  # stress test, locustfile.py필요
bentoml build    # bentofile.yaml 필요
bentoml list   # 생성된 bento 확인
bentoml serve poopup_demo:latest
--production --port 3010   # nox39에서 실패 후, 관리자 모드로 다시 창 열어 성공
bentoml containerize poopup_demo:latest  # docker image 생성
docker run -it --rm -p 3015:3000 --gpus all poopup_demo:ov37ue65xqb4
serve --production  # docker 서비스 시작
docker save -o poopup.tar poopup_demo:~~  # docker image의 hdd저장
docker load -i poopup.tar  # docker image의 재 로드

도커 실행 명령

> docker inspect <container-id>
...
"MergedDir":~,
"UpperDir":~,  # 여기 경로에 jpg파일이 저장
"WorkDir":~
...
# docker 실행(container 생성) 시,
> docker run -it --rm -p 30xx:3000 poopup_demo:kb2~~ serve --production
> docker exec -it <container-id> /bin/bash
>> cd src  # 여기에서 jpg파일 확인 가능


1. windows에서는 set 명령으로 환경변수를 볼 수 있으며, BENTOML_HOME=d:\2023으로 설정된 것 확인 가능

> set 

2. DNN학습->Bento 생성->Docker 이미지 생성의 순으로 진행됨. 

> bentoml build  # Bento파일 생성

> bentoml containerize <bentofile:tag>

3. Bento파일 생성 시에, bentofile.yaml 설정파일 사용. Custom docker를 위해서 bentofile.yaml에 지정된 Dockerfile.template 사용

{% extends bento_base_template %}
{% block SETUP_BENTO_BASE_IMAGE %}
{{ super() }}
{% endblock %}

{% set bento__user = "poop" %}
{% set bento__home = "/home/" ~  bento__user %}
{% set bento__path = "/home/" ~ bento__user ~ "/bento" %}
{% set bento__uid_gid = 1000 %}  

{% block SETUP_BENTO_COMPONENTS %}
{{ super() }}
{% endblock %}

4. 생성된 Bento파일(BENTNML_HOME 아래)의 해당 경로에 만들어진 Dockerfile을 봐서 Dockerfile.template 적용 확인 

5. Bento 파일을 이용하여 Docker 이미지 생성

> bentoml containerize poopup_demo:latest

6. 컨테이너 실행

> docker run --user poop -it --rm -p 3010:3000 --gpus all poopup_demo:leo2pupckkeizqb4 serve --production

# --------------- service.py -------------------------------------------
from __future__ import annotations
import typing as t
from typing import TYPE_CHECKING
from torchvision import transforms
import numpy as np
from PIL.Image import Image as PILImage

import bentoml
from bentoml.io import Image
from bentoml.io import NumpyNdarray


if TYPE_CHECKING:
    from numpy.typing import NDArray

poop_runner = bentoml.models.get("poopup:latest").to_runner()
svc = bentoml.Service(name="poopup_demo", runners=[poop_runner])

xforms = transforms.Compose([
        transforms.Resize(256),
        transforms.CenterCrop(224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

def to_numpy(tensor):
    return tensor.detach().cpu().numpy()


@svc.api(input=Image(), output=NumpyNdarray(dtype="int64"))
async def predict_image(f: PILImage) -> "np.ndarray[t.Any, np.dtype[t.Any]]":
    assert isinstance(f, PILImage)

    img = np.expand_dims(xforms(f), 0)
    output_tensor = await poop_runner.async_run(img)
    # print(output_tensor, type(output_tensor))
    return output_tensor.detach().cpu().numpy()

2023년 2월 15일 수요일

OPC UA python 연동

 ** OPC UA python 테스트 ** 

0. python으로 OPC UA의 서버-클라이언트 통신을 테스트한다
1. https://dibrary.tistory.com/39 (서버부) 참고해서 실행
   -단, 통신 포트를 4842에서 안되서 12346으로 해서 성공하였음
2. 아래 UaExpert 설치하여 서버에서 발생하는 데이터를 모니터링 할 수 있음
   -OPC UA python용어들에 대한 설명은 https://red-nose-cousin.tistory.com/4 참고함.
3. https://dibrary.tistory.com/38 (Client부) 참고해서 서버에서 오는 신호를 확인 가능


** UaExpert 설치 **

0. UaExpert는 OPC UA python의 서버 부분 실행 후에, 발생하는 데이터를 모니터링하는 툴
2. 회원 가입함
3. Download -> OPC UA Clients -> UaExpert를 다운로드
4. Windows10에 설치 후, 실행
매뉴얼의 12~15페이지 참고.

- UaExpert실행->Project>Server선택후 마우스 우클릭 'Add'선택->Local마우스 우클릭 후 Edit Discovery URL선택->IP와 Port number입력


# Server부 프로그램

import time
from opcua import Server

server = Server()

url = "opc.tcp://127.0.0.1:12346"
server.set_endpoint(url)

name = "OPCUA_SIMULATION_SERVER"
addspace = server.register_namespace(name)
node = server.get_objects_node()

param1 = node.add_object(addspace, "251-AM-001")
param2 = node.add_object(addspace, "251-AM-002")

normal_operation1 = param1.add_variable("ns=1; s=1630AT155-NO", "normal_operation", 0)
normal_operation2 = param2.add_variable("ns=2; i=34", "test_node", 12)
normal_operation2.set_writable()
normal_operation1.set_writable()

server.start()



# Client부 프로그램

from opcua import Client
import time

url = "opc.tcp://127.0.0.1:12346"
client = Client(url)
client.connect()

cnt = 0
while cnt <= 2:
    normal = client.get_node("ns=1; s=1630AT155-NO")
    print(normal.get_value())
    time.sleep(2)
    normal.set_value(22)
    print(normal.get_value())
    time.sleep(4)
    cnt += 1

cnt = 0
while cnt <= 2:
    normal = client.get_node("ns=2; i=34")
    print(normal.get_value())
    time.sleep(2)
    normal.set_value(12346)
    print(normal.get_value())
    time.sleep(4)
    cnt += 1



[References]


2023년 2월 13일 월요일

MySQL 사용법

 [Windows에서 MySQL 사용법]

Docker 설치 후, mysql를 pull하여 image 다운 후 실행

> docker run --name mysql_test -e MYSQL_ROOT_PASSWORD=1234 -d
-p 3306:3306 mysql:latest
> docker exec -it ee18155087ae /bin/bash
# mysql -u root -p

ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)

: 에러 메세지 나옴

> docker ps -a
ee18155087ae   mysql:latest      "docker-entrypoint.s…"   5 minutes ago   Exited (0) 7 seconds ago mysql-container
598d87a1bddc   mysql             "docker-entrypoint.s…"   8 days ago      Exited (255) 41 hours ago 0.0.0.0:3306->3306/tcp, 33060/tcp   mysql_test
....

이미 실행된 후 정지된 container있음(port 3306번을 이미 물고 있어서 오류가 남).

실행 중인 container 모두 정지 후, 기존 container 제거.

> docker stop ee18155087ae  # 실행 중인 container들 정지
> docker rm -f 598d87a1bddc  # 기존 container 제거
> docker restart ee18155087ae  # 재시작
...
# mysql -u root -p

비번 1234 넣으니 정상 실행 되며, mysql> prompt로 들어감


db생성하고, 생성된 db 선택 후, table 생성. data를 몇 개 삽입.

mysql> create database opentutorials;  # db생성
mysql> drop database opentutorials;  # db제거
mysql> show databases;  # db보기
mysql> use opentutorials;  # db선택
mysql> create table topic(  # ";" 안 넣으면 ->로 넘어감
      ->     id int(11) not null auto_increment,
      ->     title varchar(100) not null,
      ->     description text null,
      ->     created datetime not null,
      ->     author varchar(30 null,
      ->     profile varchar(100) null,
      ->     primary key(id));
mysql> show tables;  # 생성 table 확인
mysql> desc topic;  # 입력 속성 확인(description)
mysql> insert into topic (title,description,created,author,profile)
values('mysql','mysql is ...',NOW(),'kdj','developer');
mysql> select * from topic;  # 삽입된 데이터 확인
mysql> insert into topic (title,description,created,author,profile)
values('oracle','oracle is ...',NOW(),'egoing','developer');
mysql> select * from topic;
mysql> insert into topic (title,description,created,author,profile)
values('postgresql','postgresql is ...',NOW(),'egoing','data scientist, developer');
mysql> insert into topic (title,description,created,author,profile)
values('mongdb','mongodb is ...',NOW(),'egoing','developer');

일부 data만 선택하여 확인해 보기

mysql> select id,title,created,author from topic;  # 일부 속성만 선택해 data확인
# author지정 data 선택 / 순서까지 지정 / 건수도 지정
mysql> select id,title,created,author from topic where author='egoing';  
mysql> select id,title,created,author from topic where author='egoing' order by id desc;  
mysql> select id,title,created,author from topic where author='egoing'
order by id desc limit 2;  
mysql>


[python 연동]

> pip install mysql-connector-python


import mysql.connector

mydb = mysql.connector.connect(
  host="localhost",
  user="root",
  password="1234",
  database="opentutorials"
)

mycursor = mydb.cursor()
mycursor.execute("SELECT * FROM topic")
myresult = mycursor.fetchall()
for x in myresult:
  print(x)

mycursor.execute("insert into topic (title,description,created,author,profile)
       values('sqlserver','sqlserver is ...',NOW(),'kaka','database administrator')");

# 데이터베이스 변경 내용 저장
mydb.commit()

출력물:

(1, 'mysql', 'mysql is ...', datetime.datetime(2023, 5, 10, 2, 39, 5), 'kdj', 'developer')
(2, 'oracle', 'oracle is ...', datetime.datetime(2023, 5, 10, 2, 41, 9), 'egoing', 'developer')
(3, 'postgresql', 'postgresql is ...', datetime.datetime(2023, 5, 10, 2, 43, 5), 'hahaha', 'data scientist, developer')
(4, 'mongdb', 'mongodb is ...', datetime.datetime(2023, 5, 10, 2, 43, 46), 'kaka', 'developer')
(5, 'sqlserver', 'sqlserver is ...', datetime.datetime(2023, 5, 10, 5, 16, 31), 'kaka', 'database administrator')


[References]

1. https://opentutorials.org/course/3161


2023년 2월 10일 금요일

JPEG 이미지에서 GPS 위치 정보 추출 후, 주소로 전환

JPEG 이미지에서 GPS 위치 정보 추출 후, 주소로 전환.

이미지가 획득된 시간 정보도 출력. 


# From Image through GPS location to Address
from geopy.geocoders import Nominatim
from exif import Image as exImg


def geocoding_reverse(lat_lng_str):
    geolocoder = Nominatim(user_agent = 'South Korea', timeout=None)
    address = geolocoder.reverse(lat_lng_str)
    return address

def decimal_coords(coords, ref):
    decimal_degrees = coords[0] + coords[1] / 60 + coords[2] / 3600
    if ref == "S" or ref =='W' :
        decimal_degrees = -decimal_degrees
    return decimal_degrees

def image_coordinates(img):
    if img.has_exif:
        try:
            coords = (decimal_coords(img.gps_latitude, img.gps_latitude_ref),
                         decimal_coords(img.gps_longitude, img.gps_longitude_ref))
        except AttributeError:
            print ('No Coordinates')
            return {}
    else:
        print ('The Image has no EXIF information')
        return {}
    return {"imageTakenTime":img.datetime_original, "geolocation_lat":coords[0],"geolocation_lng":coords[1]}


image_path = 'bbb.jpg"
with open(image_path, 'rb') as src:
    img = exImg(src)

img_info = image_coordinates(img)
if "imageTakenTime" in img_info:
    posi = '{},{}'.format(img_info["geolocation_lat"],img_info["geolocation_lng"])
    address = geocoding_reverse(posi)
    print(img_info["imageTakenTime"], address)

#address = geocoding_reverse('36.5760732781656, 128.15935928504484')
#print(address)

2023년 2월 1일 수요일

PostgreSQL 설치 및 사용법

/* PostgreSQL 설치 및 사용법
 * (1) 설치(PostgreSQL과 DBeaver): Youbube를 참고하여 설치하였음
 * (2) SQL 기본 구문 구조 이해
 * (3) 파이썬 연결 관련
 * (4) SQL shell 명령(psql)
 * (5) 이미지 파일의 저장(BYTEA)
 * (6) 저장된 파일 경로
 *      d:\2023\postgresql\test_script.sql
 *      data도 있음
 */


/* (1) PostgreSQL과 DBeaver 설치
 *   Win10기준으로 Youtube를 참조하여 설치
 */
--자세한 내용은 Youtube를 참조함

/*
 * (2) SQL 기본 구문 구조 이해
 *   테스트 data는 (2)의 Youtube에 있음
 *   DBeaver에서 테스트(test_scripts.sql)
 */
-- 실행할 구문 선택 후 ^+Enter로 실행

select * from prod_cat_info;
select * from transactions;
select * from city;
select * from customer;


/* 테스트(필터링) 구문 */
select          count(distinct a.transaction_id) as cnt_orders
    ,       sum(a.total_amt) as sum_amt
    ,       max(a.tran_date) as latest_tran_date
from        transactions a
--where         total_amt > 0
--group by  customer_id
--having        count(discount transaction_id) >= 2
--order by  sum_amt desc
--limit         12;

-- c는 alias(별칭), distinct는 구별되는 유니크한 것만 추출


select      count(c.customer_id)
    ,       count(distinct c.transaction_id)
    ,       sum(c.total_amt)
from        transactions c;


select      a.customer_id       as  고객번호
    ,       a.tran_date         as  거래일자
    ,       a.rate              as  판매가
    ,       a.qty               as  주문수량
    ,       a.total_amt         as  주문금액
from        transactions a;


select      count(distinct  b.transaction_id)
        ,   count(distinct  b.customer_id)
        ,   sum(b.total_amt)
from        transactions b;


-- 중복포함 모두 출력
select      store_type
from        transactions;


-- 중복된 것은 제거하고 서로 다른 것만 출력
select      distinct store_type
from        transactions ;


-- 문자 형식의 리터럴은 ''으로 감싸서 입력
-- 날짜 리터럴은 date키워드와 함께 날짜형식으로 입력
-- 날짜와 nation이 일치하는 데이터만 추출
select      a.city_code
    ,       a.city_name
    ,       'KOREA'                 as  nation
    ,       date '2021-09-26'       as  insert_dt
    ,       4923                    as  number_literal
from        city a;


/* 새로운 테이블을 하나 만든다
 * 기 생성된 DB Retail아래에 mytable이란 테이블 생김
 * public -> Tables -> mytable이 생김
 */

create table mytable (
    name        varchar(80),
    pet         varchar(80)
);


insert into mytable values ('Mary', 'dog'), ('John', 'cat'), ('Robert', 'bitt');


-- 테이블 만드는 또 다른 예제
CREATE TABLE CUSTOMER
(   CUSTOMER_ID VARCHAR(200)    PRIMARY KEY,
    DOB         DATE            NOT NULL,
    GENDER      VARCHAR(200),
    CITY_CODE   VARCHAR(200)
);


/* (3) Python 연결
 * Python 코드로 어떤 테이블에 데이터 추가
 * import psycopg2
 * conn = psycopg2.connect("host='localhost' dbname='Retail' user='postgres' password='0577' port=5432")
 * cur = conn.cursor()
 * cur.execute("INSERT INTO mytable (name, pet) values ('Kdj', 'tan');")
 * conn.commit()  # 데이터 추가됨
 */


select * from mytable;


 *  cur.execute("SELECT * from mytable;")
 *  rows = cur.fetchall()
 *  rows # 출력
 *  [('Mary', 'dog'), ('John', 'cat'), ('Robert', 'bitt'), ('Kdj', 'tan')]
 */


-- 데이터 갱신
-- > cur.execute("update mytable set name='kdj' where pet='tan'")
-- > cur.execute("select * from mytable;")
-- > conn.commit()
-- > rows:
--   [('Mary', 'dog'), ('John', 'cat'), ('Robert', 'bitt'), ('lee', 'tan')]


-- 데이터 삭제
-- > cur.execute("delete from mytable where name='lee'")
-- > cur.execute("select * from mytable;")
-- > rows = cur.fetchall()
-- > rows: [('Mary', 'dog'), ('John', 'cat'), ('Robert', 'bitt')]


/* (4) SQL shell
 * >>> PostgreSQL13 -> SQL shell(psql) 실행 <<<
 * Table의 상위인 DATABASE의 조회, 생성, 삭제 가능
 * command #로 들어가서
 * \l or \l+  # 조회, 또는 상세 조회
 * CREATE DATABASE hello;  # DB생성
 * DROP DATABASE hello;  # DB제거
 * 이미 만들어진 Retail 확인 가능
 */


/* (5) 이미지 파일의 저장(BYTEA)
 * > 아래 파이썬 명령 참고
 */
 

-- > cur.execute("CREATE TABLE IF NOT EXISTS cartoon(cartoonID INTEGER, name TEXT, cartoonImg BYTEA)")
-- > conn.commit()
-- > cartoonID = 1
-- > name = "Casper"
-- > file_path = 'test.jpg'
-- > drawing = open(file_path, 'rb').read()
-- >
-- > cur.execute("INSERT INTO cartoon (cartoonID,name,cartoonImg) " + "VALUES(%s,%s,%s)", (cartoonID, name, psycopg2.Binary(drawing)))
-- > conn.commit()


-- image가 저장 되었는지 확인 가능
select *
from cartoon;

2023년 1월 30일 월요일

Windows to ubuntu ssh (powershell - ssh) 연결

 1. ubuntu - ip 확인(내부의 ip주소)

> ip a


2. SSH server설치

# ssh 설치
> sudo apt update
> sudo apt install openssh-server

# ssh 상태 확인
> sudo systemctl status ssh

# ssh 실행
> sudo systemctl start ssh

# ssh 중지
> sudo systemctl stop ssh


3. SSH server port 확인

# ssh port 확인 (실제 서비스되고 있는 port 확인)
> sudo ss -tulpn | grep ssh


4. 우분투 방화벽 설정

# 우분투 방화벽 설정 해제
> sudo ufw allow ssh


5. SSH server 연결

# ssh 연결 (우분투에서 바로 해봄)
> sudo ssh username@내부_ip_address -p sshportnumber


6. 공유기(iptime) 포트포워딩

# iptime 접속
chrome: 192.168.0.1 ->login/pw

# Port forwarding
Advanced Setup->NAT/Routing->Port Forwarding
Internal IP, External port, Internal port값을 설정(실제 서비스되고 있는 port번호)


7. window powershell 접속(원격)

# ssh 연결
> ssh username@외부_ip_address -p sshportnumber



참고 자료


2022년 9월 4일 일요일

git 사용법

처음

1. github에 들어가서 New로 새로운 repository(이름을 Processor라고 하자)를
만듬 (생성후 나오는 명령셋 참조)
2. 적당한 위치에 폴더를 만들고, vscode로 이 폴더를 오픈함
3. 폴더에서 필요한 프로그램을 작성
4. vscode의 New Terminal로 터미날을 오픈

5. 아래의 명령을 차례로 입력 (처음 업로드)
git config user.email "djk*****@d***.net"
git config user.name "djk*****"
git init (".git" 라는 폴더가 생기고현재 폴더의 변화를 추적하기 시작함)
git add filename (or git add .): 전체를 업로드하거나 변화된 파일만
업로드를 위해 파일을 staging함
git commit -m "First upload"
git remote add origin "https://github.com/galmegy/Processor.git"
(github repository와 연결)
git status: staging 상태 확인
git push -u origin master: 업로드 실행


재 수정

파일 수정 후 업로드를 원하면
git add ...부터 끝까지만 반복하면 됨


새로운 Branch

git branch Detector
git switch Detector
git status (Detector branch에 와 있음을 알 수 있음)