Windows 10 - 파일 탐색기 설정

|

파일 탐색기(Explorer)

윈도우10의 파일 탐색기는 다음 이미지와 같이 ‘바로가기’가 기본적으로 선택되어 있습니다.

image

이 자체로도 편리하게 사용할 수는 있지만, 특정 드라이버의 원하는 폴더에 접근하려면 내 PC를 선택해서 하위 트리를 열고 또 하나씩 선택해가야 하는 번거로움이 있습니다.

이를 조금 더 편리하게 사용하기 위해서는 탐색기를 실행했을 때 처음 시작 페이지를 ‘바로가기’가 아니라 ‘내 PC’로 정해줄 수 있습니다.


파일 탐색기 시작 페이지 변경

시작 페이지를 ‘내 PC’로 하기 위해서는 탐색기 폴더 설정에서 아래 이미지의 옵션값을 바꿔주면 됩니다.

image


바로가기 활용

하지만, 바로가기를 적극적으로 활용하면 더 좋을 수도 있습니다. 바로가기에 특정 폴더를 등록하고 빼는 것은 아주 간단합니다.

image

바로가기에 등록하려는 폴더에서 마우스 오른 버튼을 누르면 ‘바로가기에 고정’ 메뉴가 있습니다. 자주 사용하는 폴더들은 아예 바로가기에 고정하는 편이 탐색기를 더 편리하게 사용할 수 있을 것 같네요.

Keras - 폐암 수술 환자의 생존율 예측 예제

|

폐암 수술 환자의 생존율 예측

Keras를 활용하여 폐암 수술 환자의 생존율을 예측하는 예제 코드입니다.

예제 데이터는 여기에서 받을 수 있습니다.


surgery.py

from keras.models import Sequential
from keras.layers import Dense

import numpy

# numpy를 이용해서 csv 파일에서 데이터 불러오기
data_set = numpy.loadtxt('thoraric_surgery.csv', delimiter=',')

# X에는 0부터 17까지의 속성값
# Y에는 생존 여부(0 또는 1)
X = data_set[:, 0:17]
Y = data_set[:, 17]

# 계층 형태의 Model 생성
model = Sequential()

# Model에 계층 추가
model.add(Dense(10, input_dim=17, activation="relu"))
model.add(Dense(1, activation="sigmoid"))

# 모델 컴파일 및 학습
model.compile(loss='binary_crossentropy', optimizer='adam',
              metrics=['accuracy'])

model.fit(X, Y, epochs=50, batch_size=10)

# 결과 출력
print('\nAccuracy: {:.4f}'.format(model.evaluate(X, Y)[1]))


결과 출력

...

 10/470 [..............................] - ETA: 0s - loss: 0.3850 - acc: 0.9000
420/470 [=========================>....] - ETA: 0s - loss: 0.4528 - acc: 0.8500
470/470 [==============================] - 0s 122us/step - loss: 0.4468 - acc: 0.8532
Epoch 47/50

 10/470 [..............................] - ETA: 0s - loss: 0.0977 - acc: 1.0000
420/470 [=========================>....] - ETA: 0s - loss: 0.4454 - acc: 0.8548
470/470 [==============================] - 0s 126us/step - loss: 0.4434 - acc: 0.8532
Epoch 48/50

 10/470 [..............................] - ETA: 0s - loss: 0.1985 - acc: 1.0000
470/470 [==============================] - 0s 96us/step - loss: 0.4628 - acc: 0.8511
Epoch 49/50

 10/470 [..............................] - ETA: 0s - loss: 0.3867 - acc: 0.9000
470/470 [==============================] - 0s 96us/step - loss: 0.4423 - acc: 0.8511
Epoch 50/50

 10/470 [..............................] - ETA: 0s - loss: 0.5494 - acc: 0.8000
270/470 [================>.............] - ETA: 0s - loss: 0.4599 - acc: 0.8593
470/470 [==============================] - 0s 213us/step - loss: 0.4498 - acc: 0.8532

 32/470 [=>............................] - ETA: 0s
470/470 [==============================] - 0s 49us/step

Accuracy: 0.8532

블록체인 소개 - (1) 분산 장부

|

블록체인이 요새 뜨거운 이슈입니다. 그래서 블록체인 과제를 수행했던 경험을 기반으로 간단한 블록체인 소개글을 적어봅니다.

블록체인을 쉽게 이해하려면 ‘분산 장부(Distributed Ledgers)’를 먼저 이해하는 편이 좋습니다.


분산 장부

‘장부’란 말이 생소하게 느껴질 수도 있는데, 장부는 우리가 흔히 생각하는 돈거래 등을 할 때 기록하는 그 장부가 맞습니다. 분산 장부는 이 장부를 모든 사람들이 갖고 있자는 말입니다.

이 개념이 등장하게 된 배경을 조금 이해하기 쉽게 ‘돈거래’를 예시로 들겠습니다.

‘철수’와 ‘영희’가 돈거래를 한다고 생각합시다. 철수가 영희에게 돈 100원을 빌렸습니다.


Image

처음에는 서로의 기억에 의존해서 돈을 빌린 사실을 기억했습니다. 그러다보니 오래되니 기억도 희미해지고 누군가 거짓말을 해도 확인하기가 어려워졌습니다.


Image

그래서 영희는 장부를 적기 시작했습니다. 그랬더니 이번엔 영희가 장부에 사실만 기록했는지 확인하기가 어려워졌고, 장부가 분실되기도 했습니다.


Image

그래서 철수와 영희 모두 같은 내용의 장부를 기록하기 시작했습니다. 하지만, 철수와 영희의 장부에 서로 다른 내용이 기록되기 시작하자 누구의 장부가 진짜인지 확인하기가 어려웠고, 낮은 확률이지만 장부를 둘 다 잊어버리는 경우도 발생했습니다.


Image

그래서 철수와 영희 외 제 3의 대리인을 증인으로 해서 같은 내용의 장부를 3명이 나누어서 관리하기 시작했습니다. 부동산 거래를 생각하시면 됩니다. 매수자, 매도자, 중개인의 구도가 이와 같습니다.

물론, 이 방법도 위험 요소가 있습니다. 대리인을 100% 신뢰할 수 없다거나 등의 문제가 발생할 수 있습니다.


Image

그래서 이제 대리인을 ‘믿을 수 있는 기관’으로 대신했습니다. 은행이나 법원 등을 생각하시면 됩니다.

이게 현재의 금융 시스템의 큰 형태입니다. 모든 것은 은행이라는 중앙 서버에서 관리를 하고 사실 확인을 해줍니다.

하지만, 하나의 중앙 서버에서 모든 것을 해결하다보니 신경써야 할 점이 엄청나게 많습니다.

해커들이 수시로 노리고 있기 때문에 보안에 엄청나게 신경을 써야 합니다. 또한 수천, 수만명 그 이상의 동시 접속자가 발생하더라도 다운되지 않고 안정적으로 돌아가야 합니다. 자료들의 백업, 관리는 철저해야 합니다.

현재의 방식은 해커들로부터 정보를 보호해야하기 때문에 사용자들의 송금 정보나 계좌 정보 등은 철저하게 숨겨야 합니다.

그런데, 분산 장부는 이러한 패러다임을 완전히 바꾼 아이디어입니다. 정보를 숨기기보다는 완전히 오픈을 해버렸습니다.


Image

철수와 영희간의 거래 기록을 아예 모든 사람들이 다 같이 공유하도록 해버렸습니다. 그래서 누군가 해킹을 당해 위변조가 되더라도 나머지 장부들을 조회해서 사실 여부를 확인할 수 있도록 했습니다. 해커가 해킹을 하려면 적어도 과반수가 넘는 사람들의 장부를 전부 해킹해야 하기 때문에 보안에 안전하도록 했습니다.

여기까지가 ‘분산 장부’입니다. 블록 체인은 여기에 각 이체 내역들을 블록으로 쌓아서 체인 형태로 더 견고하고 단단하게 만든 개념입니다.

다음 번에는 블록체인에 대해서 포스팅해보도록 하겠습니다.

Visual Studio 2017 기준 C++ 프로그램 실행 후 콘솔창 안 닫히도록 하기

|

과거에는 프로그램을 작성한 후 Ctrl + F5를 누르면 콘솔 창이 닫히지 않아서 결과를 확인하기가 용이했습니다.

그런데 언제부턴지 몰라도 Ctrl + F5 키를 누르더라도 콘솔 창이 닫혀서 불편한 경우가 많이 생겼네요.

콘솔창이 안 닫히도록 하는 방법은 다음과 같습니다. (Visual Studio 2017 버전 기준입니다.)

C++ 콘솔창 안 닫히도록 하는 방법

먼저 프로젝트에 마우스 오른 버튼을 눌러 속성 메뉴를 엽니다. 주의할 점은 ‘솔루션’을 선택하고 마우스 오른 버튼을 누르는게 아니라 ‘프로젝트’를 선택해야 한다는 점입니다.

그리고 구성 속성에서 링커를 선택합니다.

image

하위 시스템콘솔(/SUBSYSTEM:CONSOLE)으로 선택합니다.

이제 Ctrl + F5 키를 누르면 결과 콘솔창이 닫히지 않고 유지되는 것을 확인할 수 있을 것입니다.

OpenCV 카메라 이미지를 Subscribe 하는 예제

|

카메라 이미지 Subscriber

여기 소스 코드를 참고했습니다.

main.cpp

#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/image.hpp"

#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#include <cstdio>
#include <memory>
#include <string>

using namespace std;
using namespace cv;

#define ROS_NODE_NAME "usb_camera_subscriber"
#define ROS_CAMERA_TOPIC_NAME "snowdeer_camera_topic"


void (*breakCapture)(int);
void signalingHandler(int signo) {
  printf("'Ctrl + C'(%d) processing...\n", signo);

  exit(1);
}

int encoding2mat_type(const string & encoding) {
  if (encoding == "mono8") {
    return CV_8UC1;
  } else if (encoding == "bgr8") {
    return CV_8UC3;
  } else if (encoding == "mono16") {
    return CV_16SC1;
  } else if (encoding == "rgba8") {
    return CV_8UC4;
  } else if (encoding == "bgra8") {
    return CV_8UC4;
  } else if (encoding == "32FC1") {
    return CV_32FC1;
  } else if (encoding == "rgb8") {
    return CV_8UC3;
  } else {
    throw std::runtime_error("Unsupported encoding type");
  }
}

string mat_type2encoding(int mat_type) {
  switch (mat_type) {
    case CV_8UC1:
      return "mono8";
    case CV_8UC3:
      return "bgr8";
    case CV_16SC1:
      return "mono16";
    case CV_8UC4:
      return "rgba8";
    default:
      throw std::runtime_error("Unsupported encoding type");
  }
}

void show_image(const sensor_msgs::msg::Image::SharedPtr msg) {
  printf("Received image #%s\n", msg->header.frame_id.c_str());

  cv::Mat frame(msg->height, msg->width, encoding2mat_type(msg->encoding),
      const_cast<unsigned char *>(msg->data.data()), msg->step);

  CvMat cvframe;
  if (msg->encoding == "rgb8") {
    cv::Mat frame2;
    cv::cvtColor(frame, frame2, cv::COLOR_RGB2BGR);
    cvframe = frame2;
  } else {
    cvframe = frame;
  }

  cvShowImage("Received Image", &cvframe);
  if( waitKey(10) == 27 ) exit(1);
}

void callback_from_image_topic(const sensor_msgs::msg::Image::SharedPtr msg) {
  show_image(msg);
}

int main(int argc, char** argv) {
  breakCapture = signal(SIGINT, signalingHandler);

  rclcpp::init(argc, argv);

  rmw_qos_reliability_policy_t reliability_policy = RMW_QOS_POLICY_RELIABILITY_RELIABLE;
  rmw_qos_history_policy_t history_policy = RMW_QOS_POLICY_HISTORY_KEEP_ALL;

  size_t depth = 10;
  setvbuf(stdout, NULL, _IONBF, BUFSIZ);

  auto node = rclcpp::Node::make_shared(ROS_NODE_NAME);
  rmw_qos_profile_t custom_qos_profile = rmw_qos_profile_default;
  custom_qos_profile.depth = depth;
  custom_qos_profile.reliability = reliability_policy;
  custom_qos_profile.history = history_policy;

  auto sub = node->create_subscription<sensor_msgs::msg::Image>(
      ROS_CAMERA_TOPIC_NAME, callback_from_image_topic, custom_qos_profile);

  rclcpp::spin(node);

  rclcpp::shutdown();

  return 0;
}