라벨이 MFC인 게시물 표시

[MFC] 파일 쓰기 다이얼로그

    static char szFilter[] = "csv Files (*.csv)||";     CFileDialog dlg(FALSE, NULL, NULL, OFN_OVERWRITEPROMPT, CString(szFilter));     if (dlg.DoModal() == IDOK) { }

[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; }

[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 -

[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

[MFC] Windows 10 OCR 만들기 : 1.Tesseract(5.0.0) 컴파일

이미지
우선 참조한 블로그 : 아는대로 지껄이는 블로그 친한 동생이 타 기관에서 자료를 받았는데  파일이 아닌 팩스나 엑셀 파일을 캡쳐하여 이미지로 보내주어 손으로  일일이 다 쳐서 업무를  진행하였단 말을 듣고 불쌍한 마음에 'OCR 간단하자나...' 라는 생각이 들어 시작하게 되었으나...  역시 이론과 실전은 다르다고 Tesseract 컴파일 하는데만 무지 시간을 잡아먹으며 삽질의 연속 이었다.  각설하고 컴파일한거 설명해보도록 하자  우선  vs2015 이상이 필요하며 CMake 도 필요하니 미리 준비하도록 하자 개발 환경 : VS2022(Preview Ver.), Windows 10 Tesseract를 컴파일 하려면 Leptonica 를 컴파일 해야하고  Leptonica 를 컴파일 하려면 여러 lib파일들이 필요한데  이는 https://github.com/peirick/Tesseract-OCR_for_Windows 에서 다운로드 가능하다. 다운로드가 완료 되면 tesseract 프로젝트를 실행하여 컴파일 하도록 하자. 처음 냅다 컴파일 하면 무지막지한 에러들을 볼 수 있다. 하지만 폴더 내에 있는 Release 폴더에 가보면 우리가 필요로 하는 lib파일들이 생성된 것을 볼 수 있다. (Tesseract-OCR_for_Windows-master\x64\Release) 자 이제 Leptonica를 컴파일 해보자 Leptonica 는 공식 사이트나 Git Hub에 있으니 둘 중 편한 Git Hub에서 받자 https://github.com/danbloomberg/leptonica git clone https://github.com/danbloomberg/leptonica.git 다운로드 후 Leptonica 폴더 안에 build 폴더랑 lib 폴더를 생성해준다. 그리고 CMake 를 실행한 후 소스 폴더와 빌드 폴더를 각각 Leptonica 폴더와 build 폴더로 지정한다.   그리고 위에서 만들었던 lib 파일들을 생성한 lib 폴

[MFC] 멀티쓰레드에서 사용하기 좋은 QUEUE (concurrent_queue)

 라인 스캔 카메라를 고속으로 사용할 일이 있어 스캔 속도를 높였더니   이미지가 뒤죽박죽이 되는 현상이 발생하였다.   아무래도 이미지를 합치기 위해 한 줄씩 카피하다보니 메모리에서 이미지 카피 속도 보다   카메라에서 던지는 속도가 더 빠른듯 하다.   일단 카메라에서 받는 이미지를 concurrent_queue 에 넣고    다른 쓰레드에서 이를 빼서 처리하는 방식으로 코드를 수정하였다.   concurrent_queue 는 멀티 쓰레드에서 사용하기 편한 Queue 로    Push 나 try_pop 을 할 때 다른 쓰레드에서의 접근을 신경쓰지 않아도 된다. CCriticalSection 을 Lock, Unlock 하지 않아도 된다는 말씀! 검색해본 결과 empty, push, get_allocator, try_pop 함수만 쓰레드 세이프 하고   다른 함수들은 접근하고 있는 쓰레드의 유무에 따라 값이 바뀔수도 있다고 한다. 사용법은 concurrent_queue<template> _QUEUE; 로 선언 후 _QUEUE.push( 객체 ); 로 push _QUEUE.try_pop(&객체) 로 Pop 하여 사용하면 된다.   #include < concurrent_queue . h > concurrent_queue<int> _QUEUE;   _QUEUE.push(1);  int a = 0; _QUEUE.try_pop(&a); --- 추가 --- 생각대로는 잘 안된다. push는 모르겠는네 try_pop 과 empty 가 동시에 두 개 이상 쓰레드에서 진행될 때  문제가 발생했다. empty로 동시에 접근하고 try_pop 할 때 문제가 발생한다;;;   어쩔 수 없이 Lock과 Unlock 을 사용하여 문제를 해결하여 사용중이다.   조금 더 공부가 필요할 것 같다. [출처] : http://egloos.zum.com/sweeper/v/3053916 [출처] : https://docs.microsoft

[MFC] 간단하게 파일 경로에서 파일 이름만 가져오기

가끔 이 망할놈의 MFC가 CString 멤버 함수 Right , ReversFind 가 안 먹힐때가 있다 이번 경우도 그러한 경우 였는데 GetLengh() 함수를 쓰니 결과가 15 ReversFind('\\')는 25로 참 기가 막혔다. 파일 이름만 분리 하려고 하는데 이러지도 저러지도 못할때 사용하기 좋은 함수 PathFindFileName(CString strPath ) 파일 이름을 리턴 해 주니 직접 멤버 함수 써서 귀찮게 하는 일이 없어 질듯 하다.

[MFC] 리본 메뉴 UI Getpos 함수 버그

이미지
리본 메뉴에 슬라이드 값을 이용하여 어떤 설정 값을 바꾸는 함수를 구현하였는데 이놈의 리본 메뉴가 고정되지 않고 숨김으로 되있는 경우 슬라이드나 값을 입력을 해도 아무런 변화가 없는 버그가 있었다 ㅠㅠ [ 슬라이더 값에 따라 아래 숫자가 바뀌어야하는데..] 같은 상황의 어느 개발자가 올린 질문 https://social.msdn.microsoft.com/Forums/en-US/9fdee956-56a5-4ae5-8081-4e6962a2a961/cmfcribbonslider-bug?forum=vcmfcatl 이 곳에 달린 코드를 이용하여 일단 값은 바뀌긴 하는데 문제는 리본 메뉴가 숨김 되었다가 다시 나타나야 값이 적용된다는 점이 아직 남아있다. 일단 이 곳에 나타난 해결책은 CMFCRibbonSlider 를 상속한 클래스를 생성하여 아래와 같은 함수를 추가하여 마우스가 눌렸다가 떼어졌을 때 마우스 위치를 이용하여 값을 셋 해주는 방식이다. 코드는 아래와 같다. (출처 : msdn ) void CMFCRibbonSliderUG::OnLButtonUp(CPoint point) {     ASSERT_VALID(this);     CMFCRibbonBaseElement::OnLButtonUp(point);     if (m_nPressed == m_nHighlighted && !IsDisabled())     {         switch(m_nPressed)         {         case nZoomInIndex:         SetPos(m_nPos + m_nZoomIncrement);         break;         case nZoomOutIndex:         SetPos(m_nPos - m_nZoomIncrement);         break;         default:         SetPos(GetPosFromPoint(point.x))

[MFC] CCriticalSection 로 공유 메모리 동시 접근 막기

멀티 쓰레드 코딩을 하다보면 쓰레드에서 공유 메모리(데이터)에 접근할 일이 많이 생긴다 이럴때 시간 순서대로 순차적으로 접근할 수도 있겠지만 동시에 같은 메모리나 데이터에 접근하여 데이터 수정 및 읽기가 진행되는 경우 데이터에 대한 오류가 발생한다 이를 방지하기 위해 MFC에서 사용 하는 것이 CCriticalSection 클래스이다. 사용 방법은 간단하다. CCriticalSection를 멤버 변수나 지역 변수로 선언해서 공유 메모리에 접근할 때 Lock() 함수를 호출 하고 사용이 끝난뒤에 Unlock() 함수를 호출하면 된다.  ex) CCriticalSection m_cs;              // CCriticalSection 객체 선언 int m_nShareData;                  // 공유 메모리 선언 m_cs.Lock();  m_nShareData + 2; // 공유 메모리 작업 실행          .          . m_cs.Unlock(); 이런식으로 작성하면 동시에 공유 메모리에 접근하는 것을 막아준다.

[MFC] 에디트 컨트롤에 계속 문자열 추가하기(List log)

리스트 로그 처럼 계속 문자열을 받아서 추가하는 함수는 컨트롤은 에디트 컨트롤을 사용하고 ReplaceSel() 를 이용해서 계속 문자열을 넣도록 하자 {     CString str;  // 문자열을 저장할 변수     m_edtLoggingOut.SetSel(-2, -1);  // 커서를 에디트박스 끝으로 이동             or     int len = m_edtLoggingOut.GetWindowTextLength();   // 글자 길이를 받아오기     m_edtLoggingOut.SetSel(len, len);      // 글자 길이만큼 커서 이동     m_edtLoggingOut.ReplaceSel(str);      // 에디트 박스에 글자 추가 } 요렇게 하면 계속 글자를 추가 할 수 있다.

[MFC] ListControl 에 image 나열 혹은 삽입하기

이미지들을 쭉 나열해야할 필요성이 있을 때 쓰기 좋.....은진 모르겠지만 나중에 또 쓸일이 있을 듯 하여 기록!!   우선 멤버 변수로 CListCtrl m_lcImageList;를 선언한 상태임  TCHAR    szPath[_MAX_PATH]; int nIndex = 0; int nIconSize = 64;  // 원본 이미지 크기가 제각각이어서 사이즈 크기 정함 static CImageList cImgList; // 이미지 리스트 초기화 if (cImgList == NULL) {     cImgList.Create(nIconSize, nIconSize, ILC_COLOR16, 2, 2); } else {     m_lcImageList.DeleteAllItems();     while (cImgList.GetImageCount())         cImgList.Remove(0); } CBitmap bmp; CImage image; CImage copyImg; // 이미지를 늘려 저장할 변수 CImage img; copyImg.Create(nIconSize, nIconSize, 16);  //카피 이미지 설정 값  // 이미지 로드 bResult = image.Load(szPath); // 읽기 성공한 경우 if (bResult == S_OK) {        // 이미지를 특정 크기로 늘리거나 줄이기         BOOL bResult = image.StretchBlt(copyImg.GetDC(), 0, 0, nIconSize, nIconSize, SRCCOPY);         // 세이브할 이미지 이름         _stprintf(szPath, 생략 );         // 이미지 세이브 : 현재 바로 입력하면 이미지가 뜨지않아 저장 후 로드한 이미지로 사용중         copyImg.Save(szPath);         Sleep(100);        

[MFC] CImage StretchBlt 검은 이미지만 나올때...

한참 동안 StretchBlt 를 이용해서 이미지를 늘려보려고 시도했으나 검은색 이미지만 나와 고생고생 했는데 허무하게 16비트 이미지로 하니 되다니..... copyImg.Create(nIconSize, nIconSize, 8); 에서 copyImg.Create(nIconSize, nIconSize, 16); 으로 사용하여 StretchBlt 함수를 사용하니 며칠동안 고생했던게 허무하게도 되더이다.. 기억해놨다가 까먹지 말고 써먹어 보자...

[MFC] Tree ctrl 에 체크박스 부모 노드 체크 시 자식 노드 체크

TV_HITTESTINFO hit_info; // 화면상에서 마우스의 위치를 얻는다. ::GetCursorPos(&hit_info.pt); // 얻은 마우스 좌표를 트리컨트롤 기준의 좌표로 변경한다. ::ScreenToClient(m_TreeCtrl_BaseFile.m_hWnd, &hit_info.pt); // 현재 마우스 좌표가 위치한 항목 정보를 얻는다. HTREEITEM current_item = m_TreeCtrl_BaseFile.HitTest(&hit_info); if(current_item != NULL) { // 마우스가 위치한 항목을 찾았다면 해당 항목을 선택한다. m_TreeCtrl_BaseFile.Select(current_item, TVGN_CARET); } HTREEITEM hNode; CString strFileName =""; CString strTestName = ""; CString strCombe = ""; hNode = m_TreeCtrl_BaseFile.GetNextItem(NULL, TVGN_CARET); // 현재 선택된 아이템의 핸들을 가져온다. strFileName = m_TreeCtrl_BaseFile.GetItemText(hNode); // 그 아이템의 이름을 얻어온다. if(strFileName.Find('[') != -1 && (hit_info.flags & TVHT_ONITEMSTATEICON) != 0) { HTREEITEM hChildItem = m_TreeCtrl_BaseFile.GetChildItem(hNode); while (hChildItem != NULL) { if (m_TreeCtrl_BaseFile.GetCheck(hNode)) { m_TreeCtrl

[MATLAB] Matlab 함수 C++ 연동 하기

Matlab 에 대해 한글로 된 자료가 적어서 원하는 자료를 찾기가 여간 어려운게 아니네.... 대부분 C로 연동하는 자료들 거기다가 오래된 자료들이라 찾는데 시간이 좀 걸림 Matlab 2014a, visual studio 2010 (32bit) Matlab 2016b, visual studio 2015 (64bit) 찾은 걸 정리하자면 1. Matlab과 Visual studio는 같은 32비트나 64비트 버젼을 사용해야함. 2. Matlab에서 'mbuild -setup' 을 입력, 사용할 컴파일러를 선택함. 3. 'deploytool' 입력하고 'Library Compiler' 선택 4. '+' 버튼을 클릭하고 C++ Library로 바꿀 m 파일 선택 5. 'Package' 버튼을 클릭하여 DLL 파일 생성 6. Visual studio 프로젝트 디렉토리에 생성된 파일 복사 7. 프로젝트 속성에서 : C/C++ -> 일반 -> 추가 경로에    '매트랩 설치 경로\extern\include' 추가 8. 링커 -> 일반 -> 추가 포함 경로     '매트랩 설치 경로\extern\lib\win64(32)\microsoft' 추가 9. 링커 -> 입력 -> 추가 종속성에 만든 lib와 'mclmcrrt.lib' 추가 10. mclInitializeApplication(NULL, 0);      AddInitialize();   // Add 는 만든 함수 이름      Add();              // 만든 함수 수행      AddTerminate();      mclTerminateApplication();      이 순서로 실행해야 됨