[MFC] Static Text 글자 색상, 배경 색상 바꾸기

 HBRUSH CDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) {     HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);     // TODO:  Change any attributes of the DC here     if (pWnd->GetDlgCtrlID() == IDC_STATIC_RESULT)     {         if (m_bResult == TRUE)         {             pDC->SetTextColor(RGB(0, 0, 0));             pDC->SetBkColor(RGB(0, 255, 0));             hbr = ::CreateSolidBrush(RGB(0, 255, 0));         }         else         {             pDC->SetTextColor(RGB(255, 255, 0));             pDC->SetBkColor(RGB(255, 0, 0));             hbr = ::CreateSolidBrush(RGB(255, 0, 0));         }     }     // TODO:  Return a different brush if the default is not desired     return hbr; }

[CUDA] CUDA 공부 2 - CUDA 기본 구조 및 함수 키워드

이미지
자 이제 GPU 메모리에 데이터를 올렸으니 연산이 들어가야 할 차례이다. 우선 CUDA를 이용하여 GPU를 연산에 사용할려면 파일 확장자를 CUDA 용으로 cu로 작성하여야 CUDA 관련 컴파일러(NVCC)가 이를 컴파일 해줄 것이다. CUDA에서 사용되는 함수는 크게 3가지로 구분된다. CPU에서 사용되는 함수, GPU에서 사용되는 함수, CPU와 GPU에서 사용되는 함수 이다. CPU와 GPU에서 사용되는 함수는 CPU에서 사용되는 함수와 GPU에서 사용되는 함수를 이어주는 다리 같은 역할이라고 이해하면 되겠다. 이 각각의 함수는 __host__, __device__, __global__ 의 키워드로 대표된다.   1. __host__ 호스트 즉, CPU와 시스템 메모리에서 실행되는 함수. 일반적으로 사용하는 함수처럼 키워드를 생략가능하다. 디바이스 함수에서 호출 불가하다.  __host__ int main() {      ... } 2. __device__ 디바이스(GPU)에서 실행되는 함수. 호스트에서 호출 불가능하다. 클래스내의 private 멤버 함수와 비슷하다고 생각하면 될 듯 하다. __device__ void function() {     ... } 3. __global__ 디바이스에서 실행되는 함수. 호스트에서 호출 가능하나 디바이스 함수에선 호출 불가하다. 호스트 함수에서 호출하여 실행하는 커널 함수를 지정하거나 디바이스 함수를 호출하는데 사용된다. 주의 점은 리턴 값은 무조건 void 이다. __global__ void function() {     ... } 위 소스는 __global__ 함수로 작성된 두 개 벡터의 값을 더해 다른 벡터에 대입하는 예제이다.(예제소스 : vectorAdd) 여기서 blockDim 과 blockIdx, threadIdx 가 보인다. 이것들이 뭔지 정확히 하고 가야 CUDA 함수를 작성할 때 혼란이 없다. 자세한 내용은 성태님의 블로그 를 확인하자. 간단히 요약하면 CUDA는 작업을 thread 단위로 수행

[C/C++, MFC] 이미지 상 두 점의 각도 구하기

이미지
 두 점간의 각도를 구하는 방법을 검색하면 거의 대부분의 글에서 atan2 함수를 사용하여 그 각도를 구하라고 한다. #include <cmath> BOOL CalculateAngle(CPoint pt1, CPoint pt2, double& dAngle) {     BOOL bResult = FALSE;     if (pt1 != pt2)     {         dAngle = atan2(pt2.y - pt1.y, pt2.x - pt1.x);         dAngle *= (180.0 / M_PI);         bResult = TRUE;     }     return bResult; } 이런 글을 보고 만든 함수가 위의 함수이다. 같은 포인트가 아닐 시 atan2 함수를 사용하여 각도를 구하고 그 결과값이 라디안 값이니 degree 값으로 바꾸는 함수이다. 이 함수를 사용해서 이미지 상 두 점의 각도를 구하니 계속 부호가 반대로 나오는 것이었다. 다음과 같이 이미지 상에 두 점 A, B가 있다고 하자 그럼 보통 우리가 생각하는 x,y 2차원 좌표상엔 B 점의 y 값이 높다. 원점(영점)이 좌하단에 위치하기 때문이다. 하지만 이미지를 다룰땐 이와 반대로 좌상단에 원점(영점)이 존재한다. 따라서 위와 같은 함수 식으론 계속 부호가 반대로 나오게 되는 것이다. A 좌표를 (100, 70) 이라 한다면 B 좌표는 (200, 40) 정도가 되어  atan2(-30, 100) 이라는 값이 들어가 마이너스 부호가 나오는 것이었다. 이미지의 특징을 생각 못한 것이었다. 따라서 함수를 다시 만들자면  #include <cmath> BOOL CalculateAngle(CPoint pt1, CPoint pt2, double& dAngle) {     BOOL bResult = FALSE;     if (pt1 != pt2)     {         dAngle = atan2((pt2.y - pt1.y) * -1, pt2.x -

[CUDA] CUDA 공부 1 - 이미지 읽어와 GPU에 복사/가져오기

이미지
 자 이제 본격적으로 해보자 우선 이미지 읽어와서 GPU에 복사, GPU 메모리 안에서 복사, GPU에서 시스템 메모리로 복사 등을 해보자.   참조한 블로그 : Z-wony 님 블로그의 [CUDA] 02. Memory Copy 및 Crop   z-wony 님은 리룩스에서 작성하셨으나 난 윈도우니까 그에 맞게 소스를 수정하고 공부해보자 우선 프로젝트를 생성하고 속성에서 opencv 와 CUDA를 추가하자. (include, lib 추가)   기존 read_JPEG_file 함수를 opencv 함수로 바꾸고     cv::Mat Img;     Img = cv::imread(SAMPLE_IMG, CV_8U);     imgWidth = Img.cols;     imgHeight = Img.rows;      imgBuffer = Img.data; 회색조 이미지 이니까 pitch * 3 된 곳을 3배를 없앤다. imageWriteToGPU 함수 안에도 opencv 함수로 수정      cv::Mat Img = cv::Mat(height, width, CV_8U, hostMem).clone();      cv::imwrite(filepath, Img); 추후 GPU 구해서 GPUDirect Storage 를 구현하면 달라지겠지만 CUDA에서 사용하는 명칭을 사용하여 설명하자 CUDA에서는 기존 메모리 (시스템 메모리) 를 Host Memory GPU 메모리를 Device Memory 라고 한다. 이 두 메모리 간에 복사 및 GPU 메모리 내의 복사를 할 때 cudaMemcpy 나 cudaMemcpy2D 함수를 사용한다. cudaMemcpy2D(devPtr, // dst Buffer (Device) pitch, // Pitch size of dst (devPtr) imgBuffer, // src Buffer (Host) (size_t)(img

[MFC] Windows 10 OCR 만들기 : OCR 적용하기(tesseract)

이미지
 일단 화면 구성은 아래와 같이 하였다. 왼쪽 이미지 리스트에서 파일을 선택하면 가운데 이미지가 나오고 오른쪽에 텍스트가 나오도록 그리고 아래쪽은 동작에 따른 로그를 출력할 계획이다. 우선은 프로젝트를 생성해주고 이전에 챙겨놨던 것들을 포함시켜 준다. 사실 안되는 것들때문에 이것 저것 추가하다보니 다 추가해버렸는데 이젠 모르겠다 ㅎㅎ 라이브러리들도 챙겨 넣고! 죄다 넣었다!!     Ctranslator.h #pragma once #include "tesseract/baseapi.h" #include "leptonica/allheaders.h" #include "opencv2/opencv.hpp" class CTranslator { private:     tesseract::TessBaseAPI* _Api;     tesseract::Tesseract* m_API; public:     CTranslator();     ~CTranslator();     void CreateTesseract();     bool Translate(cv::Mat Img, CString& strOut); }; 이왕 만드는거 클래스로 ㅋㅋ 근데 여기 C++ 소스는 배경화면이 안변하네 파이썬 소스는 뒤에 검게 변하더니... CTranslator::CTranslator() {     _Api = nullptr;     CreateTesseract(); } 생성자에서 초기화하는 함수 호출! void CTranslator::CreateTesseract() {     if(_Api == nullptr)         _Api = new tesseract::TessBaseAPI();          TCHAR chFilePath[256] = { 0, };     GetModuleFileName(NULL, chFilePath, 256);     CString strFolderPath(chFilePath);     CString

[C/C++] extern "C"

우선 참조한 블로그 들 debug me 님의 extern "C" 제대로 생각해보기 Flatinum 님의 [C/C++] extern "C"와 네임 맹글링 japa 님의 [링크에러 LNK2019] C++에서 C 함수 사용하기 [링크에러 LNK2019] C++에서 C 함수 사용하기 출처: https://ospace.tistory.com/187 [JaPa2] [링크에러 LNK2019] C++에서 C 함수 사용하기 출처: https://ospace.tistory.com/187 [JaPa2] [링크에러 LNK2019] C++에서 C 함수 사용하기 출처: https://ospace.tistory.com/187 [JaPa2] [링크에러 LNK2019] C++에서 C 함수 사용하기 출처: https://ospace.tistory.com/187 [JaPa2] 프로그램 소스들을 보면 자주 보게 되는 extern "C" 대충 C에서 C++ 함수를 사용하기 위해서 적어준다고만 알고 있었지만 윈도우에서 Visual studio 로만 코딩을 하다 보니 이게 그렇게 중요한가 라는 생각을 했었다. VS에서 주로 #include <iostream> 으로 C++ 헤더를 추가하고 printf 와 cout을 섞어 사용하다보니 별 필요성을 못 느꼈다. 물론 라이브러리들도 윈도우용이다보니 C++용이었던듯. 그러다가 리눅스로 작성을 해야하는 것이 생겨서 엄청난 귀차니즘을 맞이한적이 있다. extern "C" 는 C와 C++ 의 컴파일 방식 차이에 의해 생겨나는 미스 매치를 발생하지 않도록 하는데 그 목적이 있다. 이는 C++ 의 오버로딩 등의 기능 때문에 발생한다고 보면 될 듯하다. 자세한건 Flatinum 님의 [C/C++] extern "C"와 네임 맹글링 에서 확인해보자.  조사하다 보니 C에서 C++ 함수(라이브러리)를 사용할때도 사용되지만 C++에서 C 함수를 사용할 때도 써야