2017년 11월 23일 목요일

Windows 10 에서 시작버튼이 먹통이 되었다면?


explorer.exe 프로세스를 강제 종료 하고, 새 작업으로 실행하면 된다.

윈도우 시작 버튼 위에서 무반응인 버튼에 마우스로 우클릭 좌클릭 우클릭 좌클릭 을 반복하면 작업관리자를 강제로 불러낼 수 있다.

2017년 11월 16일 목요일

EXCEL VBA 에서 Http Request 하는 방법

VBA 도구를 만들다가 외부 API 와 통신할 일이 있어서 남기는 기록이다.
보통 Open API 를 이용하면 JSON 으로 리턴되므로 이걸 파싱해서 쓰면 된다.

아래코드를 실행 하기 전에, 참조를 추가해야 한다.

Visual Basic 도구, 참조 메뉴에서
Microsoft WinHTTP Services, version 5.1 이 사용하도록 체크되어 있어야 한다.



참고 소스 코드

Function requestHTTP()

Dim PostData As String
Dim T As String

'Web에서 가져오기, 에러 발생하면 참조모듈 확인 (Microsoft WinHttpRequest 가 참조되어야 함)
Dim httpRequest As New WinHttpRequest

'아래에 넘길 포스트 데이터를 적는다.
    PostData = "postData=_postData" 
    
        With httpRequest
        .Open "POST", "http://오픈할 Open API 주소"
        .SetRequestHeader "Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"
        .Send PostData
        .WaitForResponse: DoEvents
        T = .ResponseText
        
    End With

requestHTTP = T
    
End Function

인공지능 번역기 툴을 만들다가 남기는 후기

어플리케이션의 스트링 리소스를 한방에 (기계)번역하는 툴을 필요에 의해서 만들게 되었다.
(복붙이 너무 귀찮았어...)

구글 API 는 유료이길래 별 생각 없이 라이벌(?) 이라고 불리는 네이버 PAPAGO Open API 로 번역을 해봤다.

하루종일 삽질해서 Unity 용 툴, 엑셀용 VBA 툴 2가지를 만들었는데... (VBA가 더 어렵네 -_-;; )

막상 PAPAGO 의 번역 품질을 보니 쓰기 어려운 수준이라는 느낌을 받았다.
아래의 번역 시험 결과는 아주 소프트한 예시이다. (그나마 잘된걸 고른 것)

실제로 특수기호나 숫자가 섞이거나, 외래어 표기가 된 한글의 처리가 제대로 되지 않아서 쓰기 힘들었다.
예를 들면 "웹캠" 이라는 단어가 있으면 구글은 Web Cam 으로 PAPAGO는 "웹캠"으로 번역해버린다. (한글로 그대로 출력)

Oh My God.

뭐 가끔 쓰는 정도로 하는걸로 하고 오늘의 작업을 마무리..

Unity 툴은 에셋 스토어에 올려버렸고,

VBA 는 좀 더 다듬어서 블로그에 공개해야겠다.
누군가라도 쓰겠지 랄까 -_-;;;;

- [번역 시험 결과]----------------------------------------------

Source)
장치가 사용 중이거나 응답하지 않습니다.
영상 요청을 중단합니다.
다른 장치로 다시 시도해봐주세요.

Google)
The device is busy or not responding.
Abort video requests.
Please try again with another device.

Papago)
Device is busy or unresponsive.
Stops image request.
Try again with another device.

2017년 11월 14일 화요일

Unity WebcamTexture 의 동작에 문제가 있다면? - 해결 대안 제시

Unity API 를 통해서 장착된 WebCam을 컨트롤 해봤다.
되긴 되는데 신통찮다.

살아있는지 여부를 확인 하기 어렵고(try ~ catch 로 에러 핸들링도 불가),
각 캠이 지원하는 해상도 리스트도 가져올 수 없고 등등 불편하다.
 
안되는 장치도 있다.

Windows 10 출시 이후 발매된 웹캠 (특히, 마이크로소프트 스튜디오 시리즈)은 제대로 인식이 안된다.
장치가 1개만 설치되어 있을  때는 어영부영 돌아가는데, 2개 이상 설치되어 있을 때는 제대로 안된다.

Devices 에 인식이 제대로 안되고, 장치 이름 조차도 제대로 가져오지 못한다.

Logitech 의 웹캠은 대부분 잘 되는데, 이도 문제가 있으니...

Logitech Brio 4K 같은 경우는 고급 웹캠이라 그런지 화질과 동작 성능 양쪽에 문제가 없고
다양한 해상도와 컬러 포맷을 지원해서 그런지 Unity 와의 호환성에 크게 문제가 없다.

문제는 국민캠으로 불리는 Logitech C920 은 큰 문제가 없으나,
이 모델의 후속 기종인 C922가 문제가 된다.

640x480 의 기본 해상도는 별 차이 없이 잘 동작하는데,
1280x720 해상도를 요청하면 C922 의 경우에는 60FPS로만 동작하게 된다.
 
그러면  Unity 화면 상에서 뭔가 끊기는 느낌으로 동작하게 되는데...
왜 이런 거동을 보이는지 이해를 할 수 없지만,
내부를 본게 아니니 이해는 잠시 접어두고 방법 해결에만 집중했다.


이래저래 구글링 해외 포럼을 뒤져보니 비슷한 문제를 가진 사람이 많았고,
DirectShow를 이용해서 웹캠을 출력하면 될거라는 결론에 도달했다.

직접 만들어야 하나?
음... 더 이상 내부에서 작업량을 늘리고 싶지 않았다.


조금 더 찾아보니 다행히도 누군가 만들어둔 플러그인이 있었다. (영국의 RenderHeads 社)
AssetStore에서 아래의 Plugin의 데모 버전으로 시험해보니 큰 문제 없었기에 구입하는 것으로 결정.


[AVPro Live Camera]
https://www.assetstore.unity3d.com/kr/#!/content/3683

덱링크사의 제품까지 지원한다는데 이런 장비가 집에 없으니 모르겠고,
캡쳐카드를 통한 캡쳐도 화면이 이상하게 잘리거나 하는 문제 없이 거의 잘 되는 것 같다.

지원 플랫폼은 DirectShow를 이용하는 탓인지 Window Standalone 전용이기 때문에,
Windows에서 다양한 웹캠을 지원해야 하는
나와 비슷한 특수한 경우에 해당되는 사람들에게 추천한다.

2017년 11월 7일 화요일

Texture2D Rotate 코드

Texture2D 를 회전 시키는 코드인데,
매 Update 프레임에서 쓰기에는 오버헤드가 커서 사용하면 안된다.
그래도 어딘가 누군가에게는 도움이 될거라 생각해서 수집한 내용 기록..

# 출처 : https://answers.unity.com/questions/685656/rotate-an-image-by-modifying-texture2dgetpixels32.html

public static Texture2D RotateImage(Texture2D originTexture, int angle)
        {
            Texture2D result;
            result = new Texture2D(originTexture.width, originTexture.height);
            Color32[] pix1 = result.GetPixels32();
            Color32[] pix2 = originTexture.GetPixels32();
            int W = originTexture.width;
            int H = originTexture.height;
            int x = 0;
            int y = 0;
            Color32[] pix3 = rotateSquare(pix2, (Math.PI / 180 * (double)angle), originTexture);
            for (int j = 0; j < H; j++)
            {
                for (var i = 0; i < W; i++)
                {
                    //pix1[result.width/2 - originTexture.width/2 + x + i + result.width*(result.height/2-originTexture.height/2+j+y)] = pix2[i + j*originTexture.width];
                    pix1[result.width / 2 - W / 2 + x + i + result.width * (result.height / 2 - H / 2 + j + y)] = pix3[i + j * W];
                }
            }
            result.SetPixels32(pix1);
            result.Apply();
            return result;
        }
        static Color32[] rotateSquare(Color32[] arr, double phi, Texture2D originTexture)
        {
            int x;
            int y;
            int i;
            int j;
            double sn = Math.Sin(phi);
            double cs = Math.Cos(phi);
            Color32[] arr2 = originTexture.GetPixels32();
            int W = originTexture.width;
            int H = originTexture.height;
            int xc = W / 2;
            int yc = H / 2;
            for (j = 0; j < H; j++)
            {
                for (i = 0; i < W; i++)
                {
                    arr2[j * W + i] = new Color32(0, 0, 0, 0);
                    x = (int)(cs * (i - xc) + sn * (j - yc) + xc);
                    y = (int)(-sn * (i - xc) + cs * (j - yc) + yc);
                    if ((x > -1) && (x < W) && (y > -1) && (y < H))
                    {
                        arr2[j * W + i] = arr[y * W + x];
                    }
                }
            }
            return arr2;
        }

2017년 11월 6일 월요일

Unity Texture -> RenderTexture -> Texture2D -> Color32[] 로 변환의 험란한 길

영상 처리 작업을 하던 중 Color32[]를 이용할 일이 있었는데.
Unity 로 이걸 할라 하니 이래저래 삽질이 있었다.

적당히 구글링 해보니 Texture 를 Texture2D.ReadPixel 을 이용해서 Texture2D로 읽는 팁이 있었는데,
막상 해보니 그리는 프레임에 이걸 하면 동작하지 않는다.

좀 멀리 돌아온 감이 있는데,
텍스쳐를 렌더 텍스쳐로 바꾸고 이걸 텍스쳐2D로 만든 다음에 Colors32를 들고 오면 된다.

하루종일 삽질한 것 치고 우아하지 않아서 고민하다가..
지쳐서 그냥 이쯤에서 마무리.

C#으로는 한계가 있는 느낌.. 하아...


    private Texture2D _texture2D;
    private Texture _mainTexture;
    private RenderTexture _renderTexture;

    public Color32[] getTexture2D_AsPixel32()
    {
        if (_mainTexture == null)
            _mainTexture = _liveCamera.OutputTexture;

        if (_texture2D == null)
        {
            _texture2D = new Texture2D(_mainTexture.width, _mainTexture.height, TextureFormat.RGBA32, false);
        }
        //RenderTexture currentRT = RenderTexture.active;

        if (_renderTexture == null)
            _renderTexture = new RenderTexture(_mainTexture.width, _mainTexture.height, 32);

        // mainTexture 의 픽셀 정보를 renderTexture 로 카피
        Graphics.Blit(_mainTexture, _renderTexture);

        // renderTexture 의 픽셀 정보를 근거로 texture2D 의 픽셀 정보를 작성
        RenderTexture.active = _renderTexture;

        _texture2D.ReadPixels(new Rect(0, 0, _renderTexture.width, _renderTexture.height), 0, 0);
        _texture2D.Apply();

        return _texture2D.GetPixels32();

    }

2017년 11월 3일 금요일

해상도 값을 이용한 화면 비율 알아내기

웹캠에서 지원하는 해상도를 정리하다가
적당히 만들고 있었는데 번거로워서 만든 것
_width와 _height 를 입력하면 스트링으로 가로세로 비율이 나온다.



    // _width 는 가로 해상도, _height 는 세로 해상도 픽셀 값
    public string getResolutionRatio(int _width, int _height)
    {
        int a;
        int b;

        // 화면의 가로/세로 중 긴 쪽을 앞으로 하기
        if (_width < _height)
        {
            a = _width;
            b = _height;
        }
        else
        {
            a = _height;
            b = _width;
        }

        // 최대 공약수, 유클리드 호제법
        int gcd = gcd3(a, b);

        return string.Format("{0}:{1}", _width / gcd, _height / gcd);
    }

    private int gcd3(int a, int b)
    {
        return a % b == 0 ? b : gcd3(b, a % b);
    }