728x90
반응형

1. 개요

 - 윈도우에 파워쉘 ISE가 내장되어 있음

 - 기본 OS 설치 시 별도의 IDE, 인터프리터, 가상머신 등을 설치하지 않고 간단한 기능들을 제작할 수 있음

 

2. ISE

PowerShell ISE

 - 윈도우+R > Powershell 입력 > ISE 입력 후 엔터

 

 

3. 기본 골격

# Power Shell Script Example

function Get-SecurityEvents {
	[CmdletBinding()]
	Param(
		[Parameter(Position=0,Mandatory=$True)]
		[string]$ComputerName,
		[int]$EventID = 4634
	)   
    
    BEGIN 
    {
        $LogName = Read-Host "로그 이름을 입력하세요."        
    }
    
    PROCESS
    {
        Get-EventLog 
        -ComputerName $ComputerName `
        -LogName $LogName |
    	Where-Object -Property EventID -eq $EventID |
    	Select-Object -First 7
    }
    
	END 
    {
    }
}

# 출처: https://blog.flgram.com/827 [RedPlug's Tory]

3-1. param()

- 인수(parameter)를 정의함

- 해당 부분에 추가된 인수들은 파워쉘로 Function을 사용할 때 옵션으로 입력이 가능함

 

3-2. BEGIN{}

- 최초 한번만 실행, 필요 없을 시 공백

- 메모리 할당, 서버 기초 작업 등

 

3-3. PROCESS{}

- 함수의 주 로직이 들어가는 부분 (반복 실행됨)

 

3-4. END{}

- 정리 작업에 해당 하는 구문으로 필요없으면 비워놓는다.

- 메모리, 소켓등의 Close 작업


**출처: https://blog.flgram.com/827 [RedPlug's Tory] 블로그 참고하여 작성함.

 

 

4. 리뷰

 - 파워쉘 기능의 강력함과 편의성을 느낄 수 있었음

728x90
반응형
728x90
반응형

목적

아두이노 Leonardo Beetle(CJMCU-Beetle)로 OS에서 키보드로 인식되게 하여 입력 방지 프로그램을 우회


 

부품 구매

디바이스 마트
엘레파츠

 

제작

OS에서 시리얼 통신 방식으로 입력할 문자열을 아두이노에 전송해주면, 내부의 스크립트가 문자열을 읽어 키보드로 입력해주는 원리로 파워쉘 스크립트와 아두이노 스크립트를 작성하여 제작함.

 

1) COM포트에 문자열을 전송해주는 파워쉘

# COM1 부분은 Leonardo Beetle이 연결된 포트에 해당, 두번째 인자는 Baud Rate
$port = new-Object System.IO.Ports.SerialPort COM3,115200,None,8,one

$port.open()

# 열려진 포트에 HELLO. 문자열 Write
$port.WriteLine("HELLO.")

# 열려진 포트에 한글로 문자열 Write (한영키(Right Alt 키)를 누르면 한글로 조합됨)
$port.WriteLine("xptmxm answkduf")

$port.Close()

 

2) 아두이노 코드

// Arduino Leonardo, 115200, COM3
// 보드를 Leonardo로 설정해주고 업로드해야함
// 설정하지 않을 경우 Keyboard.h를 찾을 수 없음
#include "Keyboard.h"

void setup() {
  Serial.begin(115200);
  Keyboard.begin();
}

void my_keyinput(char ch)
{
  // delay 10ms 후 키보드 Press
  delay(10);
  Keyboard.press(ch);
  
  // delay 10ms 후 키보드 Release
  delay(10);
  Keyboard.releaseAll();
}

void loop() 
{
  // 1초 딜레이 후 시작
  delay(1000);
  Serial.println("loop start");
  
  // 입력전에 혹시 눌려진 키가 있을 수 있어 전체 Release 해줌
  delay(100);
  Keyboard.releaseAll();
  
  char temp[100];
  if(Serial.available())
  {
    // `문자열이 존재할 때까지 100bytes 씩 시리얼 포트를 읽어옴.
    byte leng = Serial.readBytesUntil('`', temp, 100); 
    
    delay(200); 
    
    // 한글자씩 분해하고 키 입력
    for(int i = 0; i < leng; i++)
    {
      Serial.print(temp[i]);
      my_keyinput(temp[i]);
    }
    Serial.println();
  }    
  
  delay(100);
  Keyboard.releaseAll();
  
  delay(1000);
  Serial.println("loop end");
}

 

 

참고사항

  • Leonardo Beetle은 아두이노 레오나르도의 Beetle 버전
  • 위의 코드는 Leonardo Beetle만 구매하면 사용이 가능함

 

728x90
반응형
728x90
반응형

1. 조회 가능 범위

  • 한국거래소(KRX)에 상장된 주식종목 리스트와 코넥스(비상장)에 있는 주식종목 리스트: 'KRX', 'KOSPI', 'KODAQ', 'KONEX'
  • 글로벌 주식종목 리스트: 'NASDAQ', 'NYSE', 'AMEX' and 'S&P500', 'SSE'(상해), 'SZSE'(심천), 'HKEX'(홍콩), 'TSE'(도쿄)
  • 한국거래소의 상장폐지종목과 관리종목 리스트: 'KRX-DELISTING'(상장폐지종목), 'KRX-ADMINISTRATIVE' (관리종목)
  • 한국, 미국, 일본의 ETF 리스트: 'KR', 'US', 'JP'
  • 주가(KRX): '005930'(삼성전자), '091990'(셀트리온헬스케어) ...
  • 주가(Word wide): 'AAPL', 'AMZN', 'GOOG'
  • 지수: 'KS11'(코스피지수), 'KQ11'(코스닥지수), 'DJI'(다우존스지수), 'IXIC'(나스닥지수), 'US500'(S&P 500지수) ...
  • 환율: 'USD/KRX', 'USD/EUR', 'CNY/KRW' ... (조합가능한 화폐별 환율 데이터 일자별)
  • 가상화폐 가격 데이터: 'BTC/USD' (Bitfinex), 'BTC/KRW' (Bithumb)

출처: https://psystat.tistory.com/113 [아카이브]

 

 

2. 달러 환율 계산기

import FinanceDataReader as fdr
import matplotlib.pyplot as plt
from datetime import date, datetime

print(fdr.__version__)
df = fdr.DataReader("USD/KRW", "2020")['Close']
print(df)

a = [date(2020, 1, 1), date(datetime.now().year, datetime.now().month, datetime.now().day)] # 시간
b = [min(df), max(df)] # 원화
c = [sum(df)/len(df), sum(df)/len(df)]

print(df[-1], sum(df)/len(df))

plt.plot(a, c)
plt.plot(df)
plt.show()

2020년 1월 1일부터 현재까지의 환율 그래프

- 현재 환율인 '1154.28원/달러'는 약 2년동안의 평균 환율인 '1157.93원/달러'보다 낮다는 것을 알 수 있다.

 

728x90
반응형

'프로그래밍 > Python' 카테고리의 다른 글

[Python] min, max 함수  (0) 2022.03.10
[python] lambda 표현식  (0) 2022.01.07
[python] 실행 시 필요한 패키지 자동 설치  (0) 2022.01.01
[Python] pykrx 모듈  (0) 2021.05.27
[Python] yfinance 모듈  (0) 2021.05.27
[Python] pycryptodome 모듈  (0) 2020.09.26
728x90
반응형

** 참고, 아래 내용과 코드는 테스트용으로 시뮬레이터로 실제 거래 목적이 아닙니다.

 

목적

  • yfinance, yahoo_fin 등의 Python 라이브러리로 시장 정보를 받아와 작성된 알고리즘을 테스트한다.
  • Ticker 별로 적합한 형태의 트레이딩 알고리즘을 개발하여 시뮬레이션해본다.
  • 최적/최고 수익을 내는 파리미터와 알고리즘, 티커를 찾아내어 실거래에 적용한다.

 

알고리즘

존버, 물타기

 기본적인 알고리즘의 전체 구조는 투자시 일반적으로 사용되는 존버(대기)와 물타기(추가 매수) 등을 기반으로 시작했다.

처음 작성된 알고리즘은 거래 시작 시점부터 현재까지 누적된 비율을 계산하여 미리 입력해둔 특정 값에 맞춰졌을 경우 매도 또는 매수를 판단하여 알려준다. 예를들면 아래 코드에서는 '변화심한그래프.거래행동판단()' 함수가 해당 기능을 담당하며 현재 티커의 주가를 입력받으면 클래스 내부에 저장된 이전 기록과 비율을 읽고 계산하여 대기(0), 매수(+a), 매도(-)를 결정해준다.


 

소스 코드

  • hwan_yfinance_module.py
from abc import *
import matplotlib.pyplot as plt
import yfinance as yf
from datetime import *
from datetime import timedelta


class yfinanace_Main(metaclass=ABCMeta):
    @abstractmethod
    def 현재가치판단(self, Ticker):
        pass
    
    @abstractmethod
    def Date_Save(self):
        pass

    @abstractmethod
    def Data_Load(self):
        pass


# 상승장 형태에서 변화가 비교적 심한 종목일 경우 적용
class 변화심한그래프(yfinanace_Main):
    # 초기 값 지정
    def __init__(self):
        self.int_보유주식수 = 0
        self.int_전일가 = 0
        self.dou_누적률 = 0.0
        self.dou_전일기준등락률 = 0
        self.dou_고정비율 = 20.0 # 주식 종목별 변경 필요

    # set
    def set_int_보유수량(self, int_보유주식수):
        self.int_보유주식수 = int_보유주식수
    def set_dou_누적률(self, dou_누적률):
        self.dou_누적률 = dou_누적률
    def set_int_보유수량(self, int_보유주식수):
        self.int_보유주식수 = int_보유주식수
    def set_int_전일가(self, int_전일가):
        self.int_전일가 = int_전일가
    
    def 내부변수_보여주기(self):
        print("현재 보유수량 : ", self.int_보유주식수, ", 누적률 : ", self.dou_누적률,
                        ", 전일가 : ", self.int_전일가)

    # 현재 시세를 입력받아 매수, 매도, 대기 를 판단해서 알려주는 함수
    def 거래행동판단(self, int_주가):
        # ex) 현재 주가가 8000원, 전일 가격이 10000원이면 전일기준 등락률은 -20% (-2000 / 10000 * 100)가 됨
        self.dou_전일기준등락률 = ((int_주가-self.int_전일가)/self.int_전일가) * 100

        # 전일 등략률을 누적함
        self.dou_누적률 = self.dou_누적률 + self.dou_전일기준등락률

        # 내부 변수 현황 출력
        #print("현재가 : "+ str(int_주가) +", 전일가 대비 등락률 :" + str(dou_전일기준등락률))
        #self.내부변수_보여주기()
        
        # 누적률이 고정비율 이상인 경우 전량 매도 후 공통 변수 초기화
        if self.dou_누적률 >= self.dou_고정비율:
            int_행동 = -1 * self.int_보유주식수
            self.dou_누적률 = 0.0 
            self.int_보유주식수 = self.int_보유주식수 + int_행동

        # 누적률이 -20%(-고정비율) 이하인 경우, 현재 누적률을 보유 주식수에 곱한 수 만큼 추가 매수
        elif self.dou_누적률 <= -1 * self.dou_고정비율:
            int_행동 = int(self.int_보유주식수 * ((self.dou_누적률/100) * -1))
            self.set_int_보유수량(self.int_보유주식수+int_행동) 

        # 누적률이 +고정비율과 -고정비율 사이일 경우(20% ~ -20%) 행동은 없음
        else:
            int_행동 = 0

        # 결정된 행동을 반환
        return int_행동

    def 현재가치판단(self, Ticker):
        print("미구현 동작입니다.")

    def Date_Save():
        print("미구현 동작입니다.")

    def Data_Load():
        print("미구현 동작입니다.")


def Simulate_변화심한그래프(str_ticker, str_startdate):
    #str_ticker = "GOOGL"
    #str_startdate = "2021-03-01"
    str_enddate = datetime.now()

    yf_Ticker = yf.Ticker(str_ticker) #AAPL, TSLA, GOOGL
    close_TickerData = yf_Ticker.history(start=str_startdate, end=str_enddate, interval="1d")['Close']

    int_최초구매수량 = 10 # 주식 종목별 최적화 필요 변수
    dou_시작주가 = close_TickerData[0]
    dou_최초투자금 = int_최초구매수량 * dou_시작주가

    # class set
    f = 변화심한그래프()
    f.set_int_보유수량(int_최초구매수량)
    f.set_int_전일가(dou_시작주가)

    print("\n초기값")
    print("Tiker :" + str_ticker + ", Start : " + str_startdate + ", Now : " + str_enddate.strftime('%Y-%m-%d') )
    f.내부변수_보여주기()
    print("")

    # 입력 기준 7일 단위로 값 가져오기 
    list_7일단위값 = []
    for i in range(1, len(close_TickerData)):    
        if i%7 == 0:
            list_7일단위값.append(close_TickerData[i])

    # 시작
    cnt = 1 
    int_전체추가투자금액 = 0

    # 시뮬레이션 Start
    for int_현재주가 in list_7일단위값:
        int_행동 = f.거래행동판단(int_현재주가)
    
        if int_행동 == 0:
            print(str(cnt) + "회 행동 : 대기")
            print("현재가 : "+ str(int_현재주가) +", 전일가 대비 등락률 :" + str(f.dou_전일기준등락률))
            print("현재 보유수량 : ", f.int_보유주식수, ", 누적률 : ", f.dou_누적률, ", 전일가 : ", f.int_전일가)
        
        elif int_행동 > 0:
            print(str(cnt) + "회 행동 : ", int_행동, "주 매수 -> 현재보유 주식 수(주) : " + str(f.int_보유주식수) + ", 추가 투자금($) : " + str(int_행동 * int_현재주가))
            int_전체추가투자금액 += (int_행동 * int_현재주가)
   
        else:
            print(str(cnt) + "회 행동 : 전량매도(", int_행동, "주), 매도 금액($) : " + str(int_행동*int_현재주가*-1))
            print("  투자 기간 : " + str_startdate + " ~ " + (datetime.strptime(str_startdate,"%Y-%m-%d") + timedelta(days=(cnt*7))).strftime('%Y-%m-%d') )
            print("  최초 투자금액 : " + str(dou_최초투자금))
            print("  추가 투자금액 : " + str(int_전체추가투자금액))
            print("  전체 투자금액 : " + str(dou_최초투자금+int_전체추가투자금액))
            print("  손익 : " + str((int_행동*int_현재주가*-1) - (dou_최초투자금 + int_전체추가투자금액)))
            break
    
        f.set_int_전일가(int_현재주가)
        print("")
        cnt += 1

    # 데이터 셋 그래프
    plt.plot(list_7일단위값)
    plt.show()

 

  • make_money.py
#-*- encoding: utf-8 -*_
import hwan_yfinance_Module as my_class

str_startDate = "2020-01-01"
arr_Ticker = ["GOOGL", "AAPL", "TSLA"]

for str_Ticker in arr_Ticker:
    my_class.Simulate_변화심한그래프(str_Ticker, str_startDate)

 

변화 심한 그래프 시뮬레이션 결과

Alphabet A (Google, Voting)/ 2020-01-01 시작

Google 시뮬레이션 결과
- 티커 : GOOGL
- 기간 : 2020-01-01 ~ 2020-06-31
- 투자 : $15502 (최초 $13394 , 추가 $2108)
- 손익 : $3413

 

AAPL(애플)/ 2020-01-01 시작

Apple 시뮬레이션 결과
- 티커 : AAPL
- 기간 : 2020-01-01 ~ 2020-04-29
- 투자 : $837 (최초 $726, 추가 $111)
- 손익 : $233

 

TSLA(테슬라) / 2020-01-01 시작

Tesla 시뮬레이션 결과
- 티커 : TSLA
- 기간 : 2020-01-01 ~ 2020-01-15
- 투자 : $837 (최초 $837, 추가 $0)
- 손익 : $302

 

리뷰 및 개선 사항

  • 현재 시뮬레이션된 알고리즘은 특정 상황, 특정 조건에서는 수익이 발생하지만,변동성이 적은 종목에서 테스트했을 경우 수익이 나지 않고, 지속적으로 하락된 상황에서는 기하급수적으로 주식을 구매함
  • 실거래 적용은 아직 큰 리스크가 있음
  • yfinance 라이브러리가 아닌 야후 finance의 개인키를 발급 받아 RestAPI를 직접 사용하는 모듈을 제작하면 더 좋을 듯함
728x90
반응형
728x90
반응형

1. 목적 및 내용 요약

Captcha 이미지를 읽어 내용을 알려주는 신경망 모델을 Python으로 작성하여 UiPath Activity 형태로 만들어준다.


 

2. Captcha 이미지 수집기 제작

RPA로 제작된 이미지 수집기


 

3. 이미지 Dataset 만들기

 3-1) 폴더 구성

  - C:\RPA\Captcha_ImageCollector\origin : 위에서 수집기가 수집한 파일들 위치

  - C:\RPA\Captcha_ImageCollector\separate : 분리된 파일들 생성

  - C:\RPA\Captcha_ImageCollector\complete : 분리가 완료된 파일 이동

폴더 구성

 3-2) 이미지 분리용 코드

import tensorflow as tf
import cv2
import os

import PIL.Image as pimage
import numpy as np
import matplotlib.image as mimage
import matplotlib.pyplot as plt

from tensorflow.keras import datasets, layers, models


# Init Flag
is_Debug = False

# Init global variables
str_path_main = "C:\RPA\Captcha_ImageCollector"
str_path_origin = str_path_main + "\\origin"
str_name_origin = "\\[index].jpeg"
str_file_origin = str_path_origin + str_name_origin
str_path_separate = str_path_main + "\\separate"
str_name_separate = "\\[index].jpeg"
str_file_separate = str_path_separate + str_name_separate
str_path_complete = str_path_main + "\\complete"
str_path_dataset = str_path_main + "\\dataset"
str_path_testset = str_path_main + "\\testset"


# 입력 경로의 파일 수를 반환
def get_current_index(str_path):
    return len(os.listdir(str_path))

# 이미지 Shape를 출력
def print_ImageShape(img, is_debug):
    if is_debug:
        _height, _width, _channel = img.shape
        print("Image Shape : " + str(_height) +", "+ str(_width) + ", " + str(_channel))

# 분리된 이미지를 생성
def Image_Separate(str_originImage):
    # separate 경로 내부의 현재 파일 수를 얻어옴
    int_index = get_current_index(str_path_separate)

    # 이미지 사이즈 변수 초기화
    origin_w = 240 # 6*40
    origin_h = 120 # 6*20
    piece_x = int(origin_w/7)

    # 원본 이미지 불러오기
    img = cv2.imread(str_originImage)
    print_ImageShape(img, is_Debug)

	# 이미지 사이즈 변경 후 테두리 공백 제거
    img = cv2.resize(img, dsize=(origin_w, origin_h)).copy()
    img = img[int(origin_h*0.05):int(origin_h*0.75), int(origin_w*0.05):int(origin_w*0.90)].copy()
    print_ImageShape(img, is_Debug)

    # 이미지 분리
    list_img = []
    img_copy = img.copy()

    for i in range(0, 6):
        list_img.append(img[:, piece_x * i:piece_x * (i+1)])
        if is_Debug: 
        	# 디버그 모드일 경우 분리할 경계선을 보라색으로 나타내줌
            result = cv2.rectangle(img_copy, (piece_x * i, 0), (piece_x * i, origin_h), (255, 0, 255), 1)
            print(piece_x * i, ", ",  piece_x*(i+1))
        
    # 분리된 이미지를 separete 경로에 파일로 출력, 뒤로 이어붙이기
    for i in range(0, 6):
        int_index = int_index + 1
        cv2.imwrite(str_file_separate.replace("[index]", str(int_index)), list_img[i])

        if is_Debug:
            cv2.imshow('img', list_img[i])
            cv2.waitKey(0)

    if is_Debug:
        result = img_copy
        cv2.imshow('result', result)
        cv2.waitKey(0)

        cv2.destroyAllWindows()
    return ;

# Function
def Start_Separate():
    # 한번에 가져올 개수, 아래 코드는 현재 경로에 있는 파일 전부를 의미함
    int_onetime = get_current_index(str_path_origin)

    last_origin_index = get_current_index(str_path_origin)
    last_complete_index = get_current_index(str_path_complete)
    print("origin start count: ", last_origin_index)
    print("complete start count : ", last_complete_index)

    # origin의 마지막 index 파일부터 가져옴 (수집기가 뒤에서부터 추가하기 때문)
    for i in reversed(range(last_origin_index + 1 - int_onetime, last_origin_index + 1)):
        str_ImageFullPath = str_file_origin.replace("[index]" , str(i))
        try:
            print(str_ImageFullPath)

            Image_Separate(str_ImageFullPath)
            print(str_path_complete + "\\" + str(i)+".jpeg")

            last_complete_index += 1
            os.rename(str_ImageFullPath, str_path_complete + "\\" + str(last_complete_index) +".jpeg")
        except:
            print(str_ImageFullPath + " - 파일 없음.")

    last_origin_index = get_current_index(str_path_origin)
    last_complete_index = get_current_index(str_path_complete)
    print("origin end count: ", last_origin_index)
    print("complete end count : ", last_complete_index)

# 분리 시작
Start_Separate()

 

3-3) 결과

중간 과정 편집

 

 3-4) 이미지 분류

 - 이미지 내부의 숫자들 중 괜찮은 이미지를 각 숫자별 폴더로 분류

 - 불량한 애들은 수작업으로 버려줌

분류 중인 이미지

   


 

4. 학습 모델 제작, 학습, 가중치 파일 생성

 - C:\RPA\Captcha_ImageCollector\dataset : 학습 시 사용할 데이터들, 폴더 별로 분류된 이미지들이 위치

 - C:\RPA\Captcha_ImageCollector\testset : 학습 완료 후 정확도를 검증하기 위한 테스트용 데이터 위치

 - 위 분리용 코드 이어서 작성

 

4-1) 학습용 코드

# 한개 이미지 가져와서 테스트
def test_OneImage(model, image_path):
    x = []
    img = cv2.imread(image_path, 0)
    
    cv2.imshow("current image", img)
    cv2.waitKey(0)

    tmp_x = cv2.resize(img, dsize = (84, 34))
    tmp_x = tmp_x.astype('int32')
    tmp_x = tmp_x.reshape(84, 34, 1)
    tmp_x = tmp_x / 255.0
    x.append(tmp_x)

    predicted_number = model.predict_classes(np.array(x))[0]

    return predicted_number

# 데이터셋 가져오기
def get_datasets(str_dataset_path):
    dataset_images = []
    dataset_labels = []

    for i in range(0, 10):
        for j in range(1, 100):
            img_name = str_dataset_path + "\\" + str(i) + "\\" + str(i) + " (" + str(j) + ").jpeg"
            try:
                img = cv2.imread(img_name, 0)
                
                x = cv2.resize(img, dsize = (84, 34))
                x = x.astype('int32')
                x = x.reshape(84, 34, 1)
                x = x / 255.0

                dataset_images.append(x)
                dataset_labels.append(i)

            except:
                None

    return dataset_images, dataset_labels

# CNN 모델
def model_CNN_ver1():
    # model 
    model = models.Sequential()

    model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(84, 34, 1)))
    model.add(layers.MaxPooling2D((2, 2)))
    #model.add(layers.Dropout(0.5))

    model.add(layers.Conv2D(64, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Dropout(0.5))

    # dense layer
    model.add(layers.Flatten())
    model.add(layers.Dense(32, activation='relu'))
    model.add(layers.Dense(10, activation='softmax'))

    model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

    return model

# 데이터셋, 테스트셋 가져오기
train_images, train_labels = get_datasets(str_path_dataset)
test_images, test_labels = get_datasets(str_path_testset)

print("가져온 학습용 데이터 수 : ",  len(train_images))
print("가져온 테스트용 데이터 수 : ",  len(test_images))

# 모델 생성
model = model_CNN_ver1()

# 모델 8회 학습
model.fit(np.array(train_images), np.array(train_labels), epochs=8)
model.save("my_model.h5")

# h5 파일 가져와서 정확도 테스트
model22 = models.load_model("my_model.h5")

# 3회 정확도 테스트
test_loss, test_acc = model.evaluate(np.array(test_images),  np.array(test_labels), verbose=3)
print("학습된 모델의 정확도 : {:5.2f}%".format(100*test_acc))

 

4-2) 학습 결과

학습 결과 91.85%

 - 대충 10번의 학습 후에 91.85%의 테스트 정확도를 가지는 my_model.h5 가중치, 모델 파일이 생성됨.

 

4-3) 가중치 파일 사용해서 정확도 테스트하기

test_images, test_labels = get_datasets(str_path_testset)
print("가져온 테스트용 데이터 수 : ",  len(test_images))

# 모델 생성
model = model_CNN_ver1()

# 파일을 불러오지 않고 모델의 정확도 테스트
test_loss, test_acc = model.evaluate(np.array(test_images),  np.array(test_labels), verbose=3)
print("학습안된 모델의 정확도 : {:5.2f}%".format(100*test_acc))

# h5 파일 가져온 뒤 정확도 테스트
model22 = models.load_model("my_model.h5")
test_loss, test_acc = model22.evaluate(np.array(test_images),  np.array(test_labels), verbose=3)
print("학습된 모델의 정확도 : {:5.2f}%".format(100*test_acc))

 

4-4) 테스트 결과

 

4-5) 이미지 한개씩 가져와서 예측된 값 보기

model22 = models.load_model("my_model.h5")

for i in range(0, 10):
    for j in range(1, 100):
        imgname = str_path_testset + "\\" + str(i) + "\\" + str(i) + " (" + str(j) + ").jpeg"
        try:
            print(test_OneImage(model22, imgname))
        except:
            print("no image files")
            None

 

4-6) 결과

 - 중간 중간 잘못 예측된 결과가 보인다. 그냥 진행한다.

현재 이미지와 결과

 


5. 원본 이미지 넣어서 한번에 결과 보기

5-1) 테스트용 원본 이미지, 학습 파일 경로 지정

학습이 완료된 h5 파일과 테스트용 이미지가 보인다.

 

5-2) 코드

# Image_Separate 기반, 6조각으로 분리된 이미지 자체를 return
def Image_Separate_2(str_originImagePath):
    # init 
    origin_w = 240 # 6*40
    origin_h = 120 # 6*20
    piece_x = int(origin_w/7)

    # Read Image
    img = cv2.imread(str_originImagePath, 0)
    img = cv2.resize(img, dsize=(origin_w, origin_h)).copy()
    img = img[int(origin_h*0.05):int(origin_h*0.75), int(origin_w*0.05):int(origin_w*0.90)].copy()

    # Separated Image 
    list_img = []

    for i in range(0, 6):
        list_img.append(img[:, piece_x * i:piece_x * (i+1)])

    return list_img;

# 이미지를 받아서 예측 값 retrun
def test_OneImage_2(model, img):
    x = []

    tmp_x = cv2.resize(img, dsize = (84, 34))
    tmp_x = tmp_x.astype('int32')
    tmp_x = tmp_x.reshape(84, 34, 1)
    tmp_x = tmp_x / 255.0
    x.append(tmp_x)

    predicted_number = model.predict_classes(np.array(x))[0]

    return predicted_number

# 분리된 이미지 list를 하나씩 넣어서 결과값 list를 만듦
def completed_module(my_model, img_path):
    list_img_2 = Image_Separate_2(img_path)
    list_result = []

    for int_index in range(0, 6):
        list_result.append(test_OneImage_2(my_model, list_img_2[int_index]))

    return list_result;

def test_FullImage():
	oringin_img_path = "test (" + str(int_index) + ").jpeg"
    for int_index in range(1, 400):
        try:
        	# 결과 출력
            print(completed_module(model22, oringin_img_path)
			
            # 원본 이미지 보여주기
            origin_img = cv2.imread(oringin_img_path)           
            cv2.imshow("result", origin_img)    
            cv2.waitKey(0)
        except:
            None

# 테스트
test_FullImage()

 

5-3) 결과

- 체감상 70~80% 확률로 성공

결과

 


6. 학습된 가중치 파일 c#에서 실행하기

 - HDF.Invoke, IronPython, Keras.Net, Tensorflow.Net 으로 코드 테스트해본 결과,

   정상동작하지 않거나 라이브러리 종속성 문제, 파이썬 3 지원안함 등의 문제로 사용 제한됨

   -> 현재사용하는 python39버전과 PythonNet Nuget의 버전을 맞춰서 설치함

 - 위에서 작성된 코드를 클래스 형태로 재작성 

 - 파이썬 코드와 h5 모듈은 실행되는 파일과 동일폴더에 위치하여야 함

   (VS의 속성 창에서 해당 파일 우클릭 > 속성 > 파일복사 칸의 값을 항상 복사로 설정하면

    실행 시마다 해당 파일이 실행 파일 옆에 복사됨)

 - 이 과정은 C#-Python 연동을 위한 테스트 코드 부분임

   Activity 제작 관련 내용은 아래 7번 항목으로 이동

 

6-1) C# 코드 (PythonNet)

nuget package manager에서 버전에 맞게 설치

using System;
using System.Text;
using System.IO;
using Python.Runtime; // PythonNet - python39버전 설치
using System.Collections.Generic;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {	
            // 엔진 초기화
            PythonEngine.Initialize();

	    // 정확하진 않지만 자원을 동결시켜 준다고함
            using (Py.GIL())
            {
            	// Import할 모듈명, HwanCaptchaModule.py
                dynamic hcm = Py.Import("HwanCaptchaModule");
                // 임포트한 모듈 내부의 Hwan_Captcha_Module 클래스 초기화
                dynamic f = hcm.Hwan_Captcha_Module("cur.jpeg", "my_model.h5");
                
                // 클래스 내의 start 메소드 실행 후 결과 출력
                Console.WriteLine(f.start());
            }
            // 엔진 종료
            PythonEngine.Shutdown();

            Console.WriteLine("Press any key...");
            Console.ReadKey();
        }
    }
}

 

6-2) Python 코드

# -*- coding: utf-8 -*-
import os
# 로그 레벨 설정으로 Tensorflow 경고 문구 제거, Tensorflow를 import하기 전에 변경해 줘야한다.
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' 

import sys
import cv2
import numpy as np
from tensorflow.keras import models

# Input : str_ImagePath, str_modelPath
# Output : str_result
class Hwan_Captcha_Module(object):
    def __init__(self, str_ImagePath, str_modelPath):
        self.str_ImagePath = str_ImagePath
        self.str_modelPath = str_modelPath
        self.model = models.load_model(self.str_modelPath)
    
    def Image_Classification(self, img):
    	# 신경망에 넣기 전 데이터 형태 가공
        x = []
        tmp_x = cv2.resize(img, dsize = (84, 34)).astype('int32').reshape(84, 34, 1) / 255.0
        x.append(tmp_x)
		
        # predict로 반환된 SoftMax 값들을 리스트 형태로 바꾸어 그 중 가장 높은 확률의 인덱스를 구함
        list = self.model.predict(np.array(x)).tolist()[0][:]
        list = list.index(max(list))
		
        # 찾아낸 인덱스가 신경망이 판단한 현재 이미지와 가장 가까운 숫자임
        return list 

    def completed_module(self):
    	origin_w = 240 # 6*40
        origin_h = 120 # 6*20
        piece_x = int(origin_w/7)

	    # 흑백 이미지로 로드(이미지의 차원을 줄임)
        img = cv2.imread(self.str_ImagePath, 0)
        img = cv2.resize(img, dsize=(origin_w, origin_h))
        # 주변 공백 제거
        img = img[int(origin_h*0.05):int(origin_h*0.75), int(origin_w*0.05):int(origin_w*0.90)]

        str_result = ""
        # 위에서 계산된 한 조각 크기만큼 옆으로 이동하면서 숫자 이미지를 가져옴.
        for i in range(0, 6):
            str_result += str(self.Image_Classification(img[:, piece_x * i:piece_x * (i+1)]))

        return str_result;
        
	# 찾아낸 결과를 return 하고 에러 발생 시 문자열 return
    def start(self):
        try:
            return self.completed_module()
        except:
            return "파일을 찾을 수 없습니다."
                        
if __name__ == "__main__":
    Hwan_Captcha_Module(sys.argv[1], sys.argv[2]).start()

 

6-3) 결과 

- 한글자씩 틀리는 경우가 종종 있지만 대부분 성공 (체감상 60~70% 성공률인 듯 하다)

- 아래 411050은 마지막이 0인지 9인지 사람이 봐도 헷갈림


7. Custom Activity 제작

 - Nuget Package Manager.exe 또는 Nuget.exe를 활용하여 .nupkg 파일 생성

 - python 코드의 종속성을 없애기 위해 6번의 코드를 one directory - exe 형태로 만든 뒤 nupkg에 포함시킴

   (auto-exe-to-py 환경 구성 및 사용법)

 - nuspec 파일로 패키지 구성을 정의할 수 있음 (자세한 내용은 MSDN 참조)

 

7-1) C# 코드 (C# 클래스 라이브러리, .Net Framework 4.6.1)

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Activities;
using System.ComponentModel;
using System.Diagnostics;

namespace ClassLibrary
{
    public class Captcha : CodeActivity
    {
        [Category("Input")]
        [RequiredArgument]
        public InArgument<String> in_str_imagepath { get; set; }

        [Category("Output")]
        public OutArgument<String> out_str_result { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            var str_imagepath = in_str_imagepath.Get(context);
            var str_result = "";
            var str_error = "";
            var str_id = "activities_captcha";
            var str_version = "1.0.7";

            var psi = new ProcessStartInfo();

            var str_h5file = Environment.GetEnvironmentVariable("userprofile") + "\\.nuget\\packages\\"+ str_id + "\\"+ str_version + "\\hcm\\model.h5";
            psi.FileName = Environment.GetEnvironmentVariable("userprofile") + "\\.nuget\\packages\\" + str_id + "\\" + str_version + "\\hcm\\Hwan_Captcha_Module.exe"; 

            psi.Arguments = string.Format("{0} {1}", str_imagepath, str_h5file);

            psi.UseShellExecute = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;

            using (var process = Process.Start(psi))
            {
                str_error = process.StandardError.ReadToEnd();
                str_result = process.StandardOutput.ReadToEnd();
                
                // 에러가 비어있지 않으면 에러 출력
                if (!string.IsNullOrEmpty(str_error))
                {
                    Console.WriteLine("error : " + str_error);
                }
            }

            out_str_result.Set(context, str_result);
        }
    }
}

 

7-2) .nuspec 파일 생성

<?xml version="1.0" encoding="utf-8"?>
<package >
  <metadata>
    <id>activities_captcha</id>
    <version>1.0.7</version>
    <title>캡챠!</title>
    <authors>hwan</authors>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <license type="expression">MIT</license>
    <description>개꿀</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <tags>Captcha</tags>
  </metadata>
  <files>
    <file src="Hwan_Captcha_Module\**" target="hcm\" />
  </files>
</package>

 

7-3) nuget.exe로 .nupkg 파일 생성하기

- nuget 파일 알아서 구하고 c:\windows 안에 두기

- nuspec있는 프로젝트 위치로 이동 후 아래 코드 실행 

nuget pack

 

7-4) 생성된 .nupkg 파일을 특정 폴더(custom-package 배포용 폴더)에 위치시킨뒤 UiPath Stuido 에서 가져옴


8. 결과

- 위의 6번과 같은 정확도로 결과가 도출됨

Custom Activity 사용

 

728x90
반응형
728x90
반응형

1. 데이터 테이블 (이하 DT)

https://docs.microsoft.com/ko-kr/dotnet/api/system.data.datatable?view=net-5.0 

 

DataTable 클래스 (System.Data)

메모리 내 데이터의 한 테이블을 나타냅니다.Represents one table of in-memory data.

docs.microsoft.com

- 윈도우의 DataTable 클래스와 동일 (C#, .Net VBA)

- C# 형태의 DataTable 사용법은 위 링크의 MS 공식문서 참조

 


2. UiPath 기본 지원 엑티비티 (Studio 설치 시 바로 사용가능)

UiPath에서 기본적으로 지원해주는 기능

- 이미지의 기능을 다 사용하지는 않지만 다른 엑티비티와 조합해서 사용하면 빠르고 간편함.

 


3. 사용 예제

Q1) Table 1을 Table 2로 만들기

- Table 1

Column1  Column2  Column3
a b c
1 2 3

- Table 2

Column1 Check Column2  Column3 Sum
a Y b c abc
1 N 2 3 123

 

A1) 

전체 Sequance
Table 1
Table 2
is_flag
str_sum
Add Data Row 내부 조건
Table 2 결과 Write line

 

Q2) 엑셀에서 데이터테이블 받아오기

A2) 생략

 

Q3) Filter Data Table, Clear DataTable, Merge DataTable, Join Data Table

A3) 생략

 

 


4. 실전 예제

Q1) Row 수가 10만건(임의의 충분히 많은 수) 정도인 DT 중 특정 데이터를 필터링하여 가져오기

이름 나이 신장 몸무게 연락처 차량 소유 여부 취미
A 10 150 50 010-0000-0000 False 게임, 영화
...            
Z 100 160 60 011-9999-9999 True 음악, 영화

- 위 DT에 데이터가 랜덤하게 8만건이 엑셀 파일로 있다고 가정했을 때,

- 나이가 30세에서 70세 사이의 키 150이상인 자차를 소유한 사람들만 가져오기

- 취미가 영화이고 나이가 50세 미만인 사람들의 이름과 연락처만 가져오기

- 연락처가 010 으로 시작하지 않는 사람들만 가져오기

A1) Linq, filter 등 사용

 

Q2) 데이터 컬럼수가 100개 이상인 DT를 가져와 수정하기

1 ... 124
a1 ... a124
b1 ... b124

- 위 DT의 값 중 컬럼명이 소수인 데이터만 가져오기

- 컬럼 명이 짝수인 값을 가져와서 중간에 Flag(값은 상관없음) 넣기

A2) Linq, filter 등 사용

 

Q3) Row 수가 변할 수 있는 DT 가져오기

 - 1회차 실행 : Row Count = 102

 - 2회차 실행 : Row Count = 95

 - 3회차 실행 : Row Count = 135

 - ... 

 - n회차 실행 : Row Count = 73

A3)

 

Q4) 입력 받은 DT의 컬럼 순서 바꾸기

- input

1 2 3 4
a b c d

-output

1 3 4 2
a c d b

A4) VBA, filter 활용

 

 


5. 응용

Q1) 원하는 컬럼 개수를 가진 임시 헤더용 DT 생성 

A1) 

// VBA 스크립트지만 하이라이팅이 없으므로 C# 주석 사용
// input : in_int_헤더개수 (input, Integer)
// output : out_dt_임시DT (output, DataTable)
Dim dt_tmp As New DataTable()

For int_i as Integer To in_int_헤더개수
	dt_tmp.Columns.Add("Columns " + int_i.ToString(), typeof(Object));
Next int_i

// Return
out_dt_임시DT = dt_tmp

 

Q2) 데이터가 있는 데이터 테이블의 헤더만 추출하기

A2) 

// 아래 내용은 VBA 코드임

 

728x90
반응형
728x90
반응형

1. Volume Lable로 디스크 문자 얻기 (네크워크 디스크 식별 시에도 가능)

// input : in_str_VolumeLavle (String)
// output : out_str_name (String)
// ex) 로컬 -> C:\
// ex) 디스크 -> C:\
// ex) 로컬 디스크 -> C:\

froeach (DriveInfo d in DriveInfo.GetDrives()){
	if(d.volumeLabel.Contains(in_str_VolumeLable)){
    		out_str_name = d.Name;
	}
}

 

728x90
반응형
728x90
반응형

1. 개요

  •  오케스트레이터 없이 단독으로 라이선스 키를 등록할 경우, UiPath.LisenceTool.exe를 사용
  •  라이선스 활성화, 비활성화, 조회 기능을 배치 파일로 제작하여 라이선스 변경 작업을 단순화함
  •  아래 경로는 UiPath 설치 기본 경로에 따라 다를 수 있음
  •  아래 코드를 메모장에 적고 .bat 확장자로 저장해서 배치파일로 활용 가능

 

2. 라이선스 활성화

@echo off
cd C:\Program Files (x86)\UiPath\Studio
UiPath.LicenseTool.exe activate -l ****-****-****-****
pause

 

3. 라이선스 비활성화

@echo off
cd C:\Program Files (x86)\UiPath\Studio
UiPath.LicenseTool.exe deactivate
pause

 

4. 현재 라이선스 상태 조회

@echo off
cd C:\Program Files (x86)\UiPath\Studio
UiPath.LicenseTool.exe info
pause

 

728x90
반응형
728x90
반응형

1. 구매 계획

1-1) 구매시 고려사항
- 1호기는 상용 FC, 무선컨트롤러 등 상용 부품을 선택할 예정
- 상용 제품들을 조립하여 250급 쿼드콥터 조립 후 제어

1-2) 프레임 선택
- Titan XL5 232mm
https://ko.aliexpress.com/item/32882570954.html?spm=a2g0o.detail.1000013.1.5dd843d0KtsCJo&gps-id=pcDetailBottomMoreThisSeller&scm=1007.13339.169870.0&scm_id=1007.13339.169870.0&scm-url=1007.13339.169870.0&pvid=d62fe2ca-44b8-40ee-8142-99d5fbbb1374&_t=gps-id:pcDetailBottomMoreThisSeller,scm-url:1007.13339.169870.0,pvid:d62fe2ca-44b8-40ee-8142-99d5fbbb1374,tpp_buckets:668%230%23131923%230_668%230%23131923%230_668%23888%233325%2320_668%23888%233325%2320_668%232846%238108%231977_668%235811%2327173%2311_668%232717%237559%2373_668%231000022185%231000066059%230_668%233468%2315615%23639_668%232846%238108%231977_668%235811%2327173%2311_668%232717%237559%2373_668%233164%239976%23933_668%233468%2315615%23639

 

7.49US $ |3K 탄소 섬유 XL5 232mm XL6 283mm XL7 294mm XL8 360mm True X FPV 프리 스타일 프레임 5 6 7 8 인치 FPV 레

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com

* 2021-06-06 알리익스프레스 기준 XL5 모델 -> 가격 : $17.83, 배송비 : $1.94 (기본 선택, 7월 10일 도착예정)


1-3) 부품 선택
- 프로펠러 : 모터에 맞게 구매
- 모터 : 개당 양력이 400g 정도면 됨 (2300kv, CW*2, CCW*2)
- 변속기 : 20A 정도로 4개
- FC : CC3D (예정)
- 송수신기 : Devo 7 (수신기 포함버전)
- PDU : 마텍 XPW 전원보드(140A, 듀얼BEC, 전류센서)
https://smartstore.naver.com/ssrc/products/586715039
- 배터리 :
- 충전기 : IMAX B6AC (단자 확인)
- 배터리 체커 :
- 전선 및 커넥터 : XT60
- 기타 : 수축튜브, 전선, 단자, 어댑터, 스트랩
https://smartstore.naver.com/ssrc/category/294584f8922e414faf32e0de306ee3c0


1-4) 참고 자료
https://www.youtube.com/watch?v=SfFl_-tof4Y


1-5) 결론
- 키트로 구매하는 게 더 저렴하기 떄문에 위 부품과 가장 비슷한 키트를 구매
- 충전기, 송수신기, 기타 소모품은 그대로 구매

2. 구매

2-1) 250급 드론 키트

Ready go -Flying 에서 주문

- BLHELI20A 변속기와 CC3D는 각각 BLHELI30A와 F4 로 대체됨 (가격 동일)
- 이미지에 해당하는 부품이 없을 경우, 현재 재고에 있는 부품으로 변경해 주는 듯함.
- 따로 구매하는 것보다 가격이 저렴하여 선택
https://ko.aliexpress.com/item/32727686945.html?spm=a2g0n.productlist.0.0.261cc697i6dT3x&browser_id=b41df9bafa2e47008f1cabd3b8284dac&aff_trace_key=&aff_platform=msite&m_page_id=mpzegyemj1icad8m179e4e8a77d7271094cc18c636&gclid=&_imgsrc_=ae01.alicdn.com%2Fkf%2FHTB1eHGzNXXXXXbkXFXXq6xXFXXXr.jpg_640x640Q90.jpg


2-2) 배터리 충전기

Onetree Charger Store에서 구매

- 오른쪽 위에 SkyRC 로고가 있는게 정품, 가품과 가격이 크게 차이나지 않지만 가품 사용 시 고생할 수 있음.
- 판매자가 구매요청 확인 시 물건을 바로 배송해줌 (응답이 빠름)
- UA 버전으로 구매 (220V)
https://ko.aliexpress.com/item/32847556295.html?spm=a2g0n.productlist.0.0.c74a171abV8ZnV&browser_id=b41df9bafa2e47008f1cabd3b8284dac&aff_trace_key=&aff_platform=msite&m_page_id=mpzegyemj1icad8m179e4f0c3d01bb3e5101a6eba7&gclid=&_imgsrc_=ae01.alicdn.com%2Fkf%2FH9eab6ab211f64e049c7dffb9d139e5add.jpg_640x640Q90.jpg

 

39201.0₩ 24% OFF|SKYRC 미니 밸런스 충전기 방전기 IMAX B6 RC 헬리콥터용, Re peak NiMH NiCD LiHV NiCd PB 리튬

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com



2-3) 송수신기

RUSFPV Store 에서 구매&nbsp;

- 보급형이면서 오래 쓸만한 10채널 송수신기, IA6 수신기가 포함된 제품으로 구매
https://ko.aliexpress.com/item/32885553734.html?spm=a2g0n.productlist.0.0.503750f1bznMAB&browser_id=b41df9bafa2e47008f1cabd3b8284dac&aff_trace_key=&aff_platform=msite&m_page_id=mpzegyemj1icad8m179e4f1e7ef23487b6c7fbd466&gclid=&_imgsrc_=ae01.alicdn.com%2Fkf%2FH878cbabe4262438fbe9520239893d110P.jpg_640x640Q90.jpg

 

53169.0₩ 48% OFF|플라이 스카이 FS i6X I6X 2.4G 10CH AFHDS 2A 라디오 송신기 X6B IA6B A8S IA10B IA6 수신기 RC 비

Smarter Shopping, Better Living! Aliexpress.com

ko.aliexpress.com



2-4) 결론
- 알리익스프레스 어플로 21년 6월 6일에 주문, 21년 6월 20일 도착 예정 (현시점 6월 9일, 6월 20일 도착완료)
- 금액은 약 19만원 소요됨 (배송비 포함, 무료 기본 배송, 카카오페이 됨)
- 배터리 제외하고 거의 모든 부품을 저렴한 가격에 해결할 수있음

 

728x90
반응형
728x90
반응형

1. 개요

 - 기본적으로 제공되는 기능이 아닌 특정 기능을 가진 Activity를 제작할 때 사용

 - C#을 기반으로 하며 패키지를 만드는 방법 중 간편한 방법을 사용할 예정임

 - Visual Studio 2019 Community, UiPath Stdio 2021.4.4 버전 사용

 


2. nupkg 생성 

확장 > 확장 관리 클릭
UiPath Activity Creator 다운로드
프로그램 재실행 후 새 프로젝트 생성
uipath 선택 후 다음 클릭
프로젝트 이름 입력
Activities 폴더 클릭 후 확장 > Add Activities 클릭
Create 클릭
입력 후 Edit 클릭
UiPath Studio > Property에서 입력 받을 인수 정의
Finish 클릭
만들어진 C# 파일 클릭
확장 후 해당 부분에 코드 작성
작성이 완료되면 .Activities 우클릭 후 게시 클릭
폴더 클릭 후 다음 클릭
nupkg 파일이 추출될 경로 입력
게시
입력한 경로에 추출된 nupkg 파일

 


3. Activity 사용

프로세스 생성
nupkg 파일 경로 입력 후 체크
추가된 패키지 경로에서 패키지 설치 후 저장
드래그 후 인수 입력

 


4. 결과

 

728x90
반응형
728x90
반응형

1. 주소

https://www.gseek.kr/member/rl/online/main.do?menuId=OTOP&menuStep=1&pMenuId=OTOP

 - 동영상 강의를 무료로 수강가능

 

경기도지식(GSEEK)

경기도 무료 온라인 평생학습서비스, 외국어, 자격취득, 생활/취미, 부모교육, 청소년 등 제공

www.gseek.kr

 

2. 개인 수강 과목

 - Sketch Up으로 도전하는 3D 모델링

 https://www.gseek.kr/member/rl/courseInfo/onCourseCsInfo.do?menuId=UB00&menuStep=2&pMenuId=OTOP&courseSeq=3580&courseCsSeq=1&courseCateCode=B100&eduTypeCode=&stuSeq= 

 

경기도지식(GSEEK)

경기도 무료 온라인 평생학습서비스, 외국어, 자격취득, 생활/취미, 부모교육, 청소년 등 제공

www.gseek.kr

 

 - 왕초보도 따라하는 ‘유니티’로 게임 만들기 - 입문편

https://www.gseek.kr/member/rl/courseInfo/onCourseCsInfo.do?menuId=UB00&menuStep=2&pMenuId=OTOP&courseSeq=1375&courseCsSeq=1&courseCateCode=B300&eduTypeCode=&stuSeq= 

 

경기도지식(GSEEK)

경기도 무료 온라인 평생학습서비스, 외국어, 자격취득, 생활/취미, 부모교육, 청소년 등 제공

www.gseek.kr

 

728x90
반응형
728x90
반응형

Ctrl + Shift + t

728x90
반응형
728x90
반응형

1. 주소 : https://www.devicemart.co.kr/main/index

 

대한민국 전자부품 1등 쇼핑몰 디바이스마트

디바이스마트

www.devicemart.co.kr

 

2. 설명

- 센서, 공구, 워크스테이션, 로봇 부품 등 판매

728x90
반응형
728x90
반응형

1. 개요

pykrx : https://github.com/sharebook-kr/pykrx

- KRX 거래소 서버에서 값 받아옴

- 국내 KOSPI, KOSDAQ, KONEX 정보 확인 가능

 

sharebook-kr/pykrx

KRX 주식 정보 스크래핑. Contribute to sharebook-kr/pykrx development by creating an account on GitHub.

github.com

 

2. 설치

pip install pykrx

 

3. 코드

from pykrx import stock

# 원하는 조건의 티커 목록 얻어오기, market 설정 안해줄 경우 기본은 KOSPI
# 아래 조건은 2021년 6월 1일 기준의 KOSDAQ 상장사들의 티커를 받아옴
tickers = stock.get_market_ticker_list("2021-06-01", market="KOSDAQ") #yyyy-MM-dd

# 각 티커들의 종목이름을 확인
for ticker in tickers:
	str_종목이름 = stock.get_market_ticker_name(ticker)
	
    # 시작일~종료일 사이 특정 티커의 OHLCV 정보를 한달 단위로 받아옴 (DateFrame)
    df = stock.get_market_ohlcv_by_date("20210101", "20210601", ticker, "m")
	print(df.head(6))

 ** 더 자세한 정보는 위 링크 참조

728x90
반응형

'프로그래밍 > Python' 카테고리의 다른 글

[python] lambda 표현식  (0) 2022.01.07
[python] 실행 시 필요한 패키지 자동 설치  (0) 2022.01.01
[Python] FinanceDataReader 모듈  (0) 2021.07.31
[Python] yfinance 모듈  (0) 2021.05.27
[Python] pycryptodome 모듈  (0) 2020.09.26
[Python] 원 나누기  (0) 2016.10.03
728x90
반응형

1. 개요

yfinance : https://pypi.org/project/yfinance/

- API와 티커 값을 사용해서 해외 주가 정보를 받아올 수 있다.

- 야후에서 제공 (무료)

- 특정 종목(티커)에 해당하는 과거 시점의 모든 데이터를 얻어올 수 있음

- Date, Open, High, Low, Close, Volume, Dividends, Stock Split 정보를 포함

- 애널리스트 평가 정보 가져오기 가능

 

yfinance

Yahoo! Finance market data downloader

pypi.org

 

2. 설치

pip install yfinance

 

3. 사용

yf_GoogleA = yf.Ticker("GOOGL") # AAPL, TSLA, GOOGL ...
yf_Tesla = yf.Ticker("TSLA")
yf_Apple = yf.Ticker("AAPL")

print(yf_GoogleA.dividends) # 배당 내역
print(yf_GoogleA.splits) # 주식분할 내역
print(yf_GoogleA.recommendations) # 애널리스트 분석 정보

# from datetime import *
# 테슬라의 2020-01-01부터 현재 시점까지 데이터를 1주 단위로 가져옴
yf_Tesla_hist = yf_Tesla.history(start="2020-01-01", end=dateTime.now, interval="1wk")

# 장마감 시의 주가 정보만 가져오기
yf_Apple_hist = yf_Apple.history(interval="1wk")['Close']

# 출력, 리스트로 변경하여 인덱스로 데이터 처리가 가능
print(list(yf_Apple_hist)[:])

# import matplotlib.pyplot as plt ,그래프 그리기
plt.plot(yf_Apple_hist)
plt.show()
728x90
반응형

'프로그래밍 > Python' 카테고리의 다른 글

[python] 실행 시 필요한 패키지 자동 설치  (0) 2022.01.01
[Python] FinanceDataReader 모듈  (0) 2021.07.31
[Python] pykrx 모듈  (0) 2021.05.27
[Python] pycryptodome 모듈  (0) 2020.09.26
[Python] 원 나누기  (0) 2016.10.03
[Python] 돌림판  (0) 2016.10.03
728x90
반응형

1. 로봇 배포하기

 - 오케스트레이터가 없이 로컬에서 작동하는 AR StandAlone 로봇이라고 가정

 - 스튜디오가 설치되어 있고 라이선스의 변경이 가능하다고 가정

 - 스튜디오에서 스크립트 작성 후 Publish 클릭 (Studio 라이선스 활용)

 - Assistant에서 내려받기 버튼 클릭

 - 배포시 로봇은

    %HomePath%\.nuget\Package\,

    %ProgramData%\UiPath\Package\

   폴더에 해당 프로젝트 이름으로 생성됨

 

 


2. 스케줄 걸어두기

 - 윈도우 작업 스케줄러 실행   

윈도우 작업 스케줄러
우클릭 &gt; 새 작업 만들기
트리거 생성
동작 생성

  ** 프로그램/스크립트(P) : ‪C:\Program Files (x86)\UiPath\Studio\UiRobot.exe

  ** 인수 추가(옵션)(A) : execute -p 배포된로봇이름

 

 

Q1 ) UiRobot.exe의 위치를 찾을 수 없음

A1 ) 아래 코드를 관리자 권한으로 실행된 cmd에 차례로 입력 후 결과 확인

# 다른 드라이브 설치 시 해당 드라이브 명을 입력하여 이동 한 뒤 아래 코드 진행
# ex) D:
cd /
dir /s /b | find /i "uirobot.exe"

결과

 

 

Q2 ) UiRobot.exe가 없음

A2 ) Studio 설치 후 재확인

 


3. 배포된 로봇 삭제하기 (수동)

 -  %ProgramData%\UiPath\Package\

 -  %HomePath%\.nuget\Package\

 배포시 생성되었던 위 경로 내부의 로봇 관련 폴더 삭제 후 Assistant 새로고침


 

728x90
반응형
728x90
반응형

H.264, MPEG, FFmpeg 관련 설명

https://beankhan.tistory.com/212



FFmpeg Visual Studio 빌드

https://sinsisao.tistory.com/2



avframe 자료형 관련 매뉴얼

https://ffmpeg.org/doxygen/2.7/structAVFrame.html



디코딩/ 인코딩 관련 예제

http://wiki.gurubee.net/pages/viewpage.action?pageId=30966295



멀티미디어 관련 글 외 다양한 글들이 잘 정리되어 있음 (구루비)

http://wiki.gurubee.net/display/SWDEV/Home



vp9 관련

https://namu.wiki/w/VP9(%EB%B9%84%EB%94%94%EC%98%A4%20%EC%BD%94%EB%8D%B1)


https://blog.naver.com/elimnet1/220687657398


https://stackoverrun.com/ko/q/4768371



gstreamer 관련

https://yujuwon.tistory.com/entry/GStreamer%EB%9E%80

728x90
반응형
728x90
반응형

** 주석처리 문자열은 VBA의 경우 ' 이지만, Tistory 코드블럭 기능에는 VBA 하이라이팅 기능이 없으므로 C# 주석인 //를 사용함.

 

1. 디렉토리 검사 후 없으면 생성

// 디렉토리 경로 검사해서 없으면 생성
If Directory.Exists("directory_path") = False Then
    Directory.CreateDirectory("directory_path")
End If

// 특정 경로 내부의 특정 키워드를 가진 파일 찾기
// input : keyword
// output : str_result ( 키워드를 가진 Full Path의 파일명과 확장자)
for each str_file as String in Directory.getFiles()
	If str_file.contain("keyword") Then
    	str_result = Path.getFileName(str_file)
    End If
Next

 

2.  현재 프로젝트의 위치를 구한 뒤 파일 복사

Dim str_curPath As String = Directory.GetCurrentDirectory()

File.Copy("source_file.txt", str_curPath + "\dest_file.txt")

 

3. 날짜 문자열 다루기

// 오늘 날짜를 특정 형식의 문자열로 변경
now.ToString("yyyyMMdd")
now.ToString("yy년 MM월 dd일")
now.ToString("yy-MM-dd")

// 특정 형식의 문자열을 DateTime으로 바꾸기, 
DateTime.Parse("yyyy-MM-dd")
DateTime.Parse("yyyy.MM.dd")

// DateTime.Parse로 인식이 안되는 날짜 양식 처리
DateTime.parseExact("20210601", "yyyyMMdd", Nothing)

// 날짜 비교
If now > DateTime.parseExact("20210601", "yyyyMMdd", Nothing) And now < DateTime.parseExact("20210630", "yyyyMMdd", Nothing)Then
	Console.writeline("현재 월 : 6월")
End If

// 현재 주의 특정 요일 날짜 구하기 (금요일 기준, 원하는 요일은 DayOfWeek.Friday 이부분 수정)
now.addDays(Int32.Parse(DayOfWeek.Friday - Today.DayOfWeek).ToString).ToString("yyyyMMdd")

 

4. 프로세스 종료

For Each str_프로세스 As Process In Process.GetProcesses()
    If str_프로세스.ToString.Contains("iexplore") Then
        str_프로세스.kill
    End If
Next

 

5. 문자열 리스트에 문자열 추가하기, List To Array

Dim list_tmp As New List(Of String)

list_tmp.add(str_input) 'input 문자열을 List에 추가

Arr_output = list_tmp.ToArray()

 

6. 이름 중간부분 마스킹 처리하기

// Input Data
str_name = "테스트"

// 문자열 처리
Dim str_star As String
Dim int_i As Integer
Dim int_dest As Integer

If str_name.Length < = 2 Then
	int_dest = str_name.Length - 1
Else
	int_dest = str_name.Length - 2
End If

For int_i = 1 To int_dest
	str_star += "*"
Next int_i


// Output Data
str_result = str_name.Replace(str_name.Substring(1, int_dest), str_star)

// ***********************
// 결과 예시
// 테 -> Error
// 테스 -> 테*
// 테스트 -> 테*트
// 테스트테 -> 테**테
// 테스트테스 -> 테***스
// ***********************

 

7. 하위 디렉토리,파일 전체 복사

FileIO.FileSystem.CopyDirectory(Source 경로, Destination 경로)
728x90
반응형
728x90
반응형

1. 소개

 https://ghidra-sre.org/

 

Ghidra

Getting Help Ghidra provides context-sensitive help on menu items, dialogs, buttons and tool windows. To access the help, press F1 or Help on any menu item or dialog. Visit our Wiki Issue Tracker

ghidra-sre.org

 

728x90
반응형
728x90
반응형

1. 개요

pycryptodome : https://pycryptodome.readthedocs.io/en/latest/

- 파이썬에서 RSA, hash 등 암호화 관련 기능 제공

 

Welcome to PyCryptodome’s documentation — PyCryptodome 3.9.9 documentation

 

pycryptodome.readthedocs.io

 

 

728x90
반응형

'프로그래밍 > Python' 카테고리의 다른 글

[Python] FinanceDataReader 모듈  (0) 2021.07.31
[Python] pykrx 모듈  (0) 2021.05.27
[Python] yfinance 모듈  (0) 2021.05.27
[Python] 원 나누기  (0) 2016.10.03
[Python] 돌림판  (0) 2016.10.03
[Python] 키로거 + 스크린샷  (0) 2016.09.18

+ Recent posts