2021년 4월 14일 수요일

Torch Points3d 사용 및 개발 방법

이 글은 Torch Points3d 사용 및 개발 방법을 간단히 다룬다. 

텐서플로우 3D가 릴리즈되었지만, 아직 당장 사용하기에는 불완전하다. 이런 이유로 토치에서 제공하는 포인트 클라우드 세그먼테이션, 객체 분류 및 인식 패키지를 사용해 보기로 한다.


파이썬 패키지 설치

PIP 설치는 매우 간단하다. Ubuntu, NVIDIA driver, CUDA, Tensorflow 등 개발환경이 설치되어 있다는 가정하에 다음과 같이 터미널에서 명령 입력한다.

pip install torch
pip install torch-points3d

소스 및 예제 설치
소스 및 예제 설치는 다음 링크 참고해 진행한다.
튜토리얼
튜토리얼 실행은 다음 링크를 참고해 진행한다.
부록: 도커 기반 OpenPCDet 사용

sudo docker run -it -v /path/to/data/on/host:/usr/src/OpenPCDet/data/kitti --rm --gpus all opheliayuan/pcdet:3.0 nvidia-smi


레퍼런스
  • PointNet from Charles R. Qi et al.: PointNet: Deep Learning on Point Sets for 3D Classification and Segmentation (CVPR 2017)
  • PointNet++ from Charles from Charles R. Qi et al.: PointNet++: Deep Hierarchical Feature Learning on Point Sets in a Metric Space
  • RSConv from Yongcheng Liu et al.: Relation-Shape Convolutional Neural Network for Point Cloud Analysis (CVPR 2019)
  • RandLA-Net from Qingyong Hu et al.: RandLA-Net: Efficient Semantic Segmentation of Large-Scale Point Clouds
  • PointCNN from Yangyan Li et al.: PointCNN: Convolution On X-Transformed Points (NIPS 2018)
  • KPConv from Hugues Thomas et al.: KPConv: Flexible and Deformable Convolution for Point Clouds (ICCV 2019)
  • MinkowskiEngine from Christopher Choy et al.: 4D Spatio-Temporal ConvNets: Minkowski Convolutional Neural Networks (CVPR19)
  • VoteNet from Charles R. Qi et al.: Deep Hough Voting for 3D Object Detection in Point Clouds (ICCV 19)
  • FCGF from Christopher Choy et al.: Fully Convolutional Geometric Features (ICCV'19)
  • PointGroup from Li Jiang et al.: PointGroup: Dual-Set Point Grouping for 3D Instance Segmentation
  • PPNet (PosPool) from Ze Liu et al.: A Closer Look at Local Aggregation Operators in Point Cloud Analysis (ECCV 2020)
  • TorchSparse from Haotian Tang et al: Searching Efficient 3D Architectures with Sparse Point-Voxel Convolution
  • PVCNN model for semantic segmentation from Zhijian Liu et al:Point-Voxel CNN for Efficient 3D Deep Learning
  • MS-SVConv from Sofiane Horache et al: 3D Point Cloud Registration with Multi-Scale Architecture and Self-supervised Fine-tuning

2021년 4월 13일 화요일

딥러닝 기반 실시간 객체 인식 YOLO v5 설치 및 사용기

이 글은 우분투 20.04기반 YOLO v5 설치 및 사용 방법을 간단히 기술한다. YOLO v5는 PyTorch기반으로 동작하며, 기존 YOLO v3보다 객체 인식 속도 및 품질이 크게 개선되었다. 

YOLO v5 성능

2020년 불과 몇 개월 사이에 YOLO v4, YOLO v5 및 PP-YOLO라는 세 가지 주요 버전의 YOLO가 릴리즈되었다. YOLO v5는 YOLO 개발자가 개발한 것이 아니기에 사람들사이에서 논쟁거리가 있었다. 하지만, 결론적으로 여러가지 성능향상이 있었기에, 많은 사람들이 v5 버전을 사용하고 있다. 참고로, 욜로 버전 역사는 다음과 같다.
  • Joseph Redmon의 YOLO 버전
버전 1: 통합 된 실시간 객체 감지(2016)
버전 2: 더 좋고, 더 빠르고, 더 강력함(2017)
버전 3: 점진적 개선(2018)
  • Joseph Redmon의 컴퓨터 비전 연구 중단 발표(2020.2)
  • Alexey Bochkovskiy의 YOLO 버전
버전 4: Darknet 기반 Tesla V100에서 65FPS의 실시간 속도. COCO 데이터 세트에서 43.5%의 AP값 획득
  • Glenn Jocher의 YOLO 버전(2020.5)
버전 5: Darknet의 포크가 아닌, PyTorch 구현. 모자이크 데이터 확대 및 자동 학습 경계 상자 앵커가 포함됨. Tesla P100에서, 이미지 당 0.007 초 객체 예측. 평균 140 FPS 주장.
YOLO v4 성능

개발환경 설치

다음 순서로 개발 환경을 설치한다.

이제, 텐서플로우나 케라스 예제 코드가 쥬피터 노트북에서 제대로 실행되면 환경 설정 성공한 것이다.
import tensorflow as tf
print(tf.reduce_sum(tf.random.normal([1000, 1000])))

import tensorflow as tf
print("# GPUs Available: ", len(tf.config.experimental.list_physical_devices('GPU')))


YOLO v5 설치
버전5는 원 개발자가 아닌 PyTorch로 YOLO개발했던 개발자가 맡아 진행한 것이다. 그러므로, PyTorch를 사용한다. 이에 대한 상세한 스토리는 여기를 참고한다. 다음을 참고해 욜로 버전5를 설치한다.
이제 YOLO 설치 폴더에서 다음 명령을 입력한다.

다음과 같이 객체 인식 처리가 되면 성공한 것이다.


주요 코드 분석
주요 코드를 분석해 본다. 동작은 다음과 같다. 
import torch.distributed as dist #파이토치 임포트
import torch.nn as nn
...
from models.yolo import Model  # 욜로 모델 임포트

def train(hyp, opt, device, tb_writer=None):
    # 설정
    if rank in [-1, 0]:
        opt.hyp = hyp  # 하이퍼 파라메터 추가
        run_id = torch.load(weights).get('wandb_id') if weights.endswith('.pt') and os.path.isfile(weights) else None
        if wandb_logger.wandb:
            weights, epochs, hyp = opt.weights, opt.epochs, opt.hyp  # WandbLogger might update weights, epochs if resuming

    nc = 1 if opt.single_cls else int(data_dict['nc'])  # 클래스 수
    names = ['item'] if opt.single_cls and len(data_dict['names']) != 1 else data_dict['names']  # class names

    # 모델 정의
    pretrained = weights.endswith('.pt')
    if pretrained:
        with torch_distributed_zero_first(rank):
            attempt_download(weights)  # download if not found locally
        ckpt = torch.load(weights, map_location=device)  # 체크 모델 로드
        model = Model(opt.cfg or ckpt['model'].yaml, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device)  # create
        model.load_state_dict(state_dict, strict=False)  # 모델 로딩
    else:
        model = Model(opt.cfg, ch=3, nc=nc, anchors=hyp.get('anchors')).to(device)  # create
    train_path = data_dict['train']
    test_path = data_dict['val']

    # 최적화
    nbs = 64  # nominal batch size
    accumulate = max(round(nbs / total_batch_size), 1)  # accumulate loss before optimizing
    hyp['weight_decay'] *= total_batch_size * accumulate / nbs  # scale weight_decay

    pg0, pg1, pg2 = [], [], []  # optimizer parameter groups

    if opt.adam:  # 최적화 함수
        optimizer = optim.Adam(pg0, lr=hyp['lr0'], betas=(hyp['momentum'], 0.999))  # adjust beta1 to momentum
    else:
        optimizer = optim.SGD(pg0, lr=hyp['lr0'], momentum=hyp['momentum'], nesterov=True)

    if opt.linear_lr:
        lf = lambda x: (1 - x / (epochs - 1)) * (1.0 - hyp['lrf']) + hyp['lrf']  # linear
    else:
        lf = one_cycle(1, hyp['lrf'], epochs)  # cosine 1->hyp['lrf']
    scheduler = lr_scheduler.LambdaLR(optimizer, lr_lambda=lf)
    # plot_lr_scheduler(optimizer, scheduler, epochs)

    # EMA
    ema = ModelEMA(model) if rank in [-1, 0] else None

    start_epoch, best_fitness = 0, 0.0
    if pretrained:
        # Epochs
        start_epoch = ckpt['epoch'] + 1
        if opt.resume:
            assert start_epoch > 0, '%s training to %g epochs is finished, nothing to resume.' % (weights, epochs)

        del ckpt, state_dict

    # Image sizes
    imgsz, imgsz_test = [check_img_size(x, gs) for x in opt.img_size]  # verify imgsz are gs-multiples

    # 모델 파라메터
    hyp['box'] *= 3. / nl  # scale to layers
    hyp['cls'] *= nc / 80. * 3. / nl  # scale to classes and layers
    hyp['obj'] *= (imgsz / 640) ** 2 * 3. / nl  # scale to image size and layers
    hyp['label_smoothing'] = opt.label_smoothing
    model.nc = nc  # attach number of classes to model
    model.hyp = hyp  # attach hyperparameters to model
    model.gr = 1.0  # iou loss ratio (obj_loss = 1.0 or iou)
    model.class_weights = labels_to_class_weights(dataset.labels, nc).to(device) * nc  # attach class weights
    model.names = names

    for epoch in range(start_epoch, epochs):  # epoch 
        model.train()  # 모델 훈련

        for i, (imgs, targets, paths, _) in pbar:  # 배치 -------------------------------------------------------------
            ni = i + nb * epoch  # number integrated batches (since train start)
            imgs = imgs.to(device, non_blocking=True).float() / 255.0  # uint8 to float32, 0-255 to 0.0-1.0


detect.py 주요 코드는 다음과 같다. 
def detect(save_img=False):
    source, weights, view_img, save_txt, imgsz = opt.source, opt.weights, opt.view_img, opt.save_txt, opt.img_size
    save_img = not opt.nosave and not source.endswith('.txt')  # save inference images
    webcam = source.isnumeric() or source.endswith('.txt') or source.lower().startswith(
        ('rtsp://', 'rtmp://', 'http://', 'https://'))

    # 초기화
    device = select_device(opt.device)
    half = device.type != 'cpu'  # half precision only supported on CUDA

    # 모델 로드
    model = attempt_load(weights, map_location=device)  # load FP32 model
    stride = int(model.stride.max())  # model stride
    imgsz = check_img_size(imgsz, s=stride)  # check img_size

    # 클래스 이름 및 색상 
    names = model.module.names if hasattr(model, 'module') else model.names
    colors = [[random.randint(0, 255) for _ in range(3)] for _ in names]

    # 예측 실행
    if device.type != 'cpu':
        model(torch.zeros(1, 3, imgsz, imgsz).to(device).type_as(next(model.parameters())))  # run once
    t0 = time.time()
    for path, img, im0s, vid_cap in dataset:
        img = torch.from_numpy(img).to(device)
        img = img.half() if half else img.float()  # uint8 to fp16/32
        img /= 255.0  # 0 - 255 to 0.0 - 1.0
        if img.ndimension() == 3:
            img = img.unsqueeze(0)

        # Inference
        t1 = time_synchronized()
        pred = model(img, augment=opt.augment)[0]

        # Apply Classifier
        if classify:
            pred = apply_classifier(pred, modelc, img, im0s)  # 객체 인식 예측

        # 객체 탐지 프로세스
        for i, det in enumerate(pred):  # detections per image
            p = Path(p)  # to Path
            save_path = str(save_dir / p.name)  # img.jpg
            gn = torch.tensor(im0.shape)[[1, 0, 1, 0]]  # normalization gain whwh
            if len(det):
                # Rescale boxes from img_size to im0 size
                det[:, :4] = scale_coords(img.shape[2:], det[:, :4], im0.shape).round()

            # Stream results
            if view_img:
                cv2.imshow(str(p), im0)
                cv2.waitKey(1)  # 1 millisecond

if __name__ == '__main__':
    parser = argparse.ArgumentParser()  # 객체 탐지 예측 파라메터 정의
    parser.add_argument('--weights', nargs='+', type=str, default='yolov5s.pt', help='model.pt path(s)')
    parser.add_argument('--source', type=str, default='data/images', help='source')  # file/folder, 0 for webcam
    parser.add_argument('--img-size', type=int, default=640, help='inference size (pixels)')
    parser.add_argument('--conf-thres', type=float, default=0.25, help='object confidence threshold')
    parser.add_argument('--iou-thres', type=float, default=0.45, help='IOU threshold for NMS')
    parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')
    parser.add_argument('--view-img', action='store_true', help='display results')
    parser.add_argument('--save-txt', action='store_true', help='save results to *.txt')
    parser.add_argument('--save-conf', action='store_true', help='save confidences in --save-txt labels')
    parser.add_argument('--nosave', action='store_true', help='do not save images/videos')
    parser.add_argument('--classes', nargs='+', type=int, help='filter by class: --class 0, or --class 0 2 3')
    parser.add_argument('--agnostic-nms', action='store_true', help='class-agnostic NMS')
    parser.add_argument('--augment', action='store_true', help='augmented inference')
    parser.add_argument('--update', action='store_true', help='update all models')
    parser.add_argument('--project', default='runs/detect', help='save results to project/name')
    parser.add_argument('--name', default='exp', help='save results to project/name')
    parser.add_argument('--exist-ok', action='store_true', help='existing project/name ok, do not increment')
    opt = parser.parse_args()
    print(opt)
    check_requirements(exclude=('pycocotools', 'thop'))

    with torch.no_grad():
        if opt.update:  # update all models (to fix SourceChangeWarning)
            for opt.weights in ['yolov5s.pt', 'yolov5m.pt', 'yolov5l.pt', 'yolov5x.pt']:  # 가중치에 따른 예측
                detect()
                strip_optimizer(opt.weights)
        else:
            detect()

마무리
YOLO v5는 실행 속도 측면에서 분명한 이점이 있다. YOLO v5 모델은 작은 개체를 감지하는 데 더 나은 성능을 보이면서, 빠르게 실행된다. 다음은 다른 딥러닝 모델과 성능 차이를 나타낸다.


간단한 AWS EC2 클라우드 서비스 사용, 터미널 접속 및 웹서버 개발

이 글은 간단한 AWS EC2 클라우드 서비스 사용 방법을 정리한것이다. 이 글은 아마존 AWS EC2 클라우드 서비스 사용, 터미널 접속 및 웹서버 개발을 보여준다.

AWS 서비스 신청 및 인스턴스 생성

AWS에서 EC2 서비스 신청한 후, 서비스에서 적당한 인스턴스를 선택하여 생성한다. 

이런 모든 작업은 다음 AWS 데쉬보드의 각 메뉴에서 제공해준다. 


데쉬보드 메뉴 리스트(왼쪽)에서 인스턴스 메뉴 선택하고, 아래 화면에서 인스턴스 시작 버튼을 선택한다.

다음과 같이 이미 저장된 인스턴스 이미지들이 리스트된다. 이 글에서는 우분투 18.04 이미지를 인스턴스로 생성한다. 생성 시 순서는 화면을 읽어보며 따라가면 된다. 인스턴스 생성시 보안키를 생성할 수 있다. 보안키 파일 pem파일을 생성하고 다운로드받아 보관한다.

인스턴스 실행하면, 자동으로 해당 이미지가 아마존 서버에 로딩되고, 운영체제가 실행된다. 네트워크는 자동으로 아마존에서 제공되는 공개IP와 연결된다. 

터미널 접속 및 패키지 설치

실행 후, 인스턴스에 관련 패키지를 설치하기 위하여, 명령창을 관리자 모드로 실행한다. 명령창에서 ssh 터미널을 다음과 같이 실행한다. 

ssh -i "???.pem" ubuntu@ec2-##-##-##-###.ap-northeast-2.compute.amazonaws.com

???부분은 인스턴스 시작 시 생성되는 보안키 파일이다. ###은 해당 인스턴스의 공개 DNS주소이다. 이 주소는 다음과 같이 인스턴스 데쉬보드의 인스턴스에 연결 메뉴에서 얻을 수 있다. pem은 인스턴스 생성 시 다운로드받은 보안키 파일명 경로이다. pem 설정 뒤에 있는 부분은 인스턴스 접속 DNS 공개 주소이다.  

실행하면 다음과 같이 ssh 터미널에 접속된다. 혹시, "Permissions for 'private-key' are too open" 에러 발생 시 pem파일 속성에서 불필요한 파생 계정을 삭제하고 실행한다(상세 내용 참고).


이제 원격으로 접속된 아마존 서버에 기본적인 node.js 등 설치하여 사용한다(설치 참고).
sudo apt-get install npm

간단한 웹서버 코딩 및 실행
다음과 같이 express를 설치한다. 
npm install express

다음과 같이 js 파일을 생성한다. 
nano server.js

다음과 같이 코딩한다.
const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello World!')
})

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
})

3000번 포트에서 접속 가능하도록, AWS 인스턴스 데쉬보드 보안 탭에서 보안그룹 링크를 클릭하여, 방화벽의 인바우드 규칙을 다음과 같이 설정한다(참고. 아마존 CORS 설정).

이제 노드 서버를 실행해보고, 외부 네트워크에서 접속되는 지 확인한다(참고. 터미널 종료 후 서비스 계속 실행 방법).
screen
node server.js &

다음과 같이 각자 공개 DNS 주소에 접속되면 성공한 것이다.

마무리
AWS 서비스는 서버, 운영체제, 네트워크 설치 노가다를 크게 줄여준다. 이런 것들은 해본 사람도 설치에만 몇일 이상이 걸린다. AWS는 가입 후 AWS에서 제공하는 콘솔 데쉬보드에서 몇번의 클릭으로 웹서버, 데이터베이스서버, 딥러닝 패키지, IoT 패키지 등 이미지를 서버에 업로드해 실행시킨다. AWS의 가장 큰 단점은 비싼 비용과, AWS에 너무 특화된 서비스이다. 특히, 데이터 저장소, 네트워크 밴드폭 사용 비용 등이 비싼데, 아무 생각없이 신청했다가는 요금 포탄 맞을 수 있으니 주의가 필요하다.


2021년 4월 10일 토요일

가장 쉬운 Ubuntu 18.04 NVIDIA driver, CUDA and Tensorflow installation

이 글은 Ubuntu 18.04 NVIDIA driver, CUDA and Tensorflow 설치 방법에 대한 것을 간략히 정리한 것이다. 그동안 18.04 버전 설치 테크트리가 약간 변경되어 다시 재정리한다. 다만, 딥러닝 등 최신 라이브러리 사용 목적이라면 우분투 20.04를 권장한다.
  • Ubuntu 18.04 설치 이미지 부팅 가능 USB 만들기
  • Install Ubuntu 18.04. 만약, 화면이 안보이거나 멈추면 GRUB에서 NOMODESET 추가 후 설치 진행
  • Booting Ubuntu
  • Ubuntu에서 Terminal을 열어 아래 명령어 입력 실행함 
    • ubuntu-drivers devices
    • sudo ubuntu-drivers autoinstall
    • reboot
    • nvidia-smi
  • Install CUDA 10.2 and 11.2 or 11.0. 주의: 이 단계에서 GPU 드라이버 재 설치하면 안됨.
  • Install cuDNN SDK 8.0.4
  • Install Tensorflow
  • Install Keras
  • Install Jupyter Notebook
  • reboot
이제, 다음과 같이 딥러닝 예제들이 정상 실행되면 성공한 것이다.
결과

참고로, Ubuntu 18.04 현재 버전은 ROS 설치를 완벽히 지원하지 않는다. 디펜던시 에러가 발생하므로 주의한다.

2021년 4월 8일 목요일

대체불가능 토큰 NFT 개념과 직접 만들어보기

이 글은 대체불가능 토큰 NFT 만드는 방법을 간략히 설명한다. 

최근, 언론에 작가 비플이 NFT 기술을 접목해 만든 이미지 파일 한 점이 2021.11 미국 뉴욕 크리스티 경매에서 약 780억원에 낙찰된것으로 알려지면서 NFT에 대한 관심이 많아지고 있다. 비플 말고도, 트레버 존슨의 '비트코인 천라'라는 작품들 중 하나는 428만원에 거래되는 등 거래량도 늘어나고 있다. 엘론 머스크의 아내이자 가수인 그라임스도 대체불가능한 토큰(NFT)으로 20분 만에 65억을 벌었다. 

이 글은 NFT 개념과 만드는 방법을 간략히 이야기한다.

Everydays: The first 5000 days (NFT)
The Bitcoin Angel

머리말
대체 불가능한 토큰 (NFT) 은 독립형 암호화 토큰 유형이다. 대체 불가능한 토큰은 검증 가능한 디지털 컨텐츠 희소성을 보장하는 데 사용될 수 있다. 

비트코인은 1BT가 동일한 가치를 보장해, 코인 간 서로 대체가 가능한 토큰인 반면, NFT는 각 토큰이 서로 다른 가치를 저장할 수 있다. 서로 다른 가치를 토큰이 가지므로, 토큰끼리는 서로 대체 불가능하다. NFT는 1 토큰 당 가치가 모두 다르다. 

NFT도 물론 블록체인속에 저장 및 기록되어, 소유권 확인 및 추적, 거래 내역 등을 지원한다. NFT는 어떤 종류의 고유한 항목이 필요한 산업에 유용 할 수 있다. 예를 들어 예술 작품이나 사용자의 고유한 업적을 식별하는 데 사용된다. 

다른 지갑에 두 개의 비트 코인이 있다면 완전히 동일하다. 두 개의 NFT는 내부 값이나 토큰 특이성에서 개별적으로 서로 같지 않다. 구별은 대체 불가능한 토큰에 할당된 해시값으로 처리한다. 

블록 체인 세계에 구축되고있는 금융 시스템은 큰 단점이 있다. 예를 들어, 부동산 자산은 산업 요구 사항에 따라 설정된 자산별 복잡성 및 보안 요구사항으로 인해 블록 체인에서 디지털 정보로 완전히 표현할 수 없는 경우가 많다. 기존 자금 조달 프로세스(IPO), 블록 체인 산업(ICO, IEO, STO)에 대해서도 마찬가지이다. 

현재 시가 총액은 아직 매우 적다. 자산에 대한 현물 가격이 부족하기 때문에, 암호 화폐 시장에 비해 측정하기가 더 어렵다. 2차 거래량(peer-to-peer)을 기준으로 월별 수치는 $2-3백만에 가깝다. 2018년 크립토 키티(CryptoKitties)의 광고 이후 NFT와 상호 작용하는 사용자의 수는 느리지만 지속적으로 증가하고 있다.

Standard를 통해 개발자는 자산별로 동작을 프로그래밍하고, NFT를 기반으로 하는 자산의 기능과 상호작용하는 방법에 대한 자세한 지침을 설정할 수 있다.
NFT 개발방법

이런 표준 및 코딩 없이도 NFT 생성을 지원하는 서비스를 사용해, 자신의 컨텐츠를 NFT화할 수 있다. 다음은 NFT 지원 서비스 웹사이트이다.
  • Opensea: 암호화된 디지털 아이템 판매 마켓
  • Mintable: 블록체인 아이템 판매 마켓
  • SuperRare: 디지털 예술품 소장 및 거래 

NFT 표준 개념
이 표준은 CryptoKitties에서 처음 사용되었다. ERC-721은 대체 불가능한 디지털 자산 생성을위한 최초의 규약이다. 언급된 표준의 가장 큰 이점은 개발자가 간단히 OpenZeppelin도구를 통해 ERC-721호환 계약을 작성할 수 있다는 것이다. 이 규약은 계정 간의 가치를 교환하는 다음과 같은 인터페이스를 구현해야 한다.

    function balanceOf(address _owner) external view returns (uint256);
    function ownerOf(uint256 _tokenId) external view returns (address);
    function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;
    function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
    function approve(address _approved, uint256 _tokenId) external payable;
    function setApprovalForAll(address _operator, bool _approved) external;
    function getApproved(uint256 _tokenId) external view returns (address);
    function isApprovedForAll(address _owner, address _operator) external view returns (bool);

ERC-721은 transferFrom 메소드를 사용하여 이러한 자산을 전송하는 방법도 제공한다.
여기에서 ERC-721 에 대한 자세한 내용 (기술 사양 포함)을 확인할 수 있다.

ERC-1155
ERC-1155를 개발 한 Enjin 팀은 NFT 에 반 대체성에 대한 아이디어를 가져 왔다. 표준은 단일 자산이 아닌 여러 자산 그룹을 나타낼 수 있다.  
여기에서 ERC-1155 에 대한 자세한 내용을 확인할 수 있다 .

Non-Ethereum Standards
블록 체인 중 하나인 FLOW는 NFT 프로젝트에 개방되어 있으며 이미 NBA , UFC 및 기타 유명 기업과 제휴하여 이러한 브랜드의 팬들을 위한 공동 독점 NFT 아이템을 개발했다. 여기에서 FLOW 블록 체인으로 NFT를 만드는 방법에 대해 자세히 알아볼 수 있다 .

직접 만들어보는 NFT
원래는 NFT를 만들기 위해서, 이더리움 가스(GAS)나 이더(ETH)를 구입해 비용을 지불해야 한다. 하지만, Mintable에 NFT를 생성하면, 가스를 지불하지 않고도 작업을 시작할 수 있다. 

전체 NFT 개발 순서는 다음과 같다.

전자지갑 개설(은행계좌 개설) - 지갑 연결 및 생성 - 판매 아이템 등록 - 아이템 판매

다음과 같이 서비스 무료 계정을 생성한다. 이메일 주소로 전송된 인증 코드를 입력한다.

이제, MetaMask 지갑을 만들자. 크롬에서 여기를 클릭해, 브라우저 확장을 설치한다.

새로운 MetaMask 지갑을 시작한다.

지갑을 설정하려면 비밀번호를 제출해야한다. 그 답례로 12 개의 무작위 단어 목록 인 "시드 문구"를 받게된다. 어딘가에 적어 둔다. 이후, 다음을 클릭해, 해당 시드 문구를 확인해야 한다. 통과하면 다음 메시지를 만나게 된다.

그리고, 보유한 이더(ETH)를 확인할 수 있다.

이제, Mintable로 돌아가서“Mint an item”을 클릭한다. 

지갑에 NFT가 이미 존재하는지 (존재하지 않음) 또는 새 지갑을 생성하는지 (현재 존재 함)를 선택하라는 메시지가 표시된다. 

Mintable은 기본적으로 가스없는 NFT로 설정된다. 여기서 원하는 것을 업로드 할 수 있으며, 판매 또는 양도 될때까지 블록 체인에 들어 가지 않는다(물론, 수수료가 발생하지 않는다). 만약, 예전 방식으로 작업을 수행하려면 슬라이더를 클릭하고, 고급 모드로 이동하여 트랜잭션 모델을 선택할 수 있다(대신 수수료 지급해야 함).

다음과 같이 MetaMask와 지갑을 연결한다.

이제, 다음과 같이, 자신의 컨텐츠를 NFT로 생성할 수 있는 아이템 작성 및 판매 화면이 보일것이다. 

이제, 가치가 있는 자신의 컨텐츠를 업로드하고, 개별 파일이 있다면 추가하면 된다. 그 결과 다음과 같이 대체불가능한 토큰으로 처리된 작품이 등록된다. 여기서는 강선우가 작업 디자인한 The Beatles 패러디 작품을 등록해 보았다. 그 결과는 다음과 같다.
마무리
NFT의 모든 규약을 마스터하고, NFT를 만들수도 있지만, 그렇지 않고, 이를 지원하는 서비스를 이용해 만들 수도 있다. NFT는 아직 초기 단계이므로, 여러가지 이슈가 있다. NFT를 판매할 때는 비용 구조를 완벽히 이해해야 한다. 판매 시 가스 수수료, 거래 수수료 등을 지급해야 한다. 이런 부분을 이해하지 않고, 진행하면 손해를 볼 수도 있다. 

현재 NFT로 팔리는 것은 상상을 초월한다. TZCOLORS는 색상도 판매하고 있는 데, 1111XTZ는 한화 500만원에 팔리기도 했다. 앞으로 NFT는 어느 정도로 성장할지는 확실치 않지만, 사람들이 많은 관심을 가지리라는 것은 예상할 수 있다.

레퍼런스

2021년 4월 6일 화요일

MongoDB 시계열 데이터 분석 질의, 데이터 분석 가시화 및 자동 요약 트리거 개발

이 글은 시계열 데이터 분석 시 필요한 데이터 쿼리, 데이터 분석 시각화, 시계열 데이터 자동 요약 트리거 개발 방법을 다룬다. 


몽고디비의 쿼리는 SQL형식과는 다른 도큐먼트, 컬렉션에 대한 JSON 형식과 유사한 질의 언어를 사용한다. 다음과 같은 스키마로 데이터가 저장되어 있다고 가정한다.

{_id : ObjectId, sensor : String, area : String, date : String, value : Int32}

만약, sensor 중 "light"센서의 value 값이 150보다 작은 레코드만 얻도록 질의하려면 아래와 같이 필터를 만들어 실행하면 된다.

{sensor: 'light', value: {$lt: 150}}

쿼리 연산자는 아래와 같이 매우 다양하다. 

상세한 내용은 Query and Projection Operators를 참고한다. 

쿼리를 해서 원하는 데이터 레코드를 얻으면, Export data 기능을 이용해 아래와 같이 엑셀 파일 등을 저장할 수 있다.

만약, 데이터 분석을 통한 차트 시각화가 필요하다면, 아래 MongoDB chart를 사용하면 된다. 참고로, 여기서 제공하는 서버는 AWS 등에서 운영되며, 제한된 기능에서 무료로 MongoDB 인스턴스를 제공하기 때문에 부담없이 사용이 가능하다.

몽고디비 서버 인스턴스가 생성되면 다음과 같은 데쉬보드를 확인할 수 있다.

기존에 사용했던 데이터베이스에서 엑셀 저장 기능을 이용해 데이터를 MongoDB charts 서버로 옮길 수 있다. 

데이터를 입력한 후에는 다음과 같이 데이터를 분석해 차트 그래프로 가시화할 수 있다.