반응형

오늘 WinRT로 프로젝트를 제작하면서 OpenCV를 사용해야해서 OpenCV 코드를 작성하고 컴파일을 했는데 컴파일은 분명 잘되는데 프로그램을 실행하면서 처음에는 잘 되다가 다시 실행하면 아래 사진 처럼 오류가 난다.. 도무지 모르겠는데.. 그러다가 12시간 동안 뭔 문제인지 찾다가 알아냈다. (참고로 진짜 12시간 걸렸다.)

Windows 스토어 응용 프로그램 'APP_ID'을(를) 활성화할 수 없습니다. 활성화 요청이 실패했습니다(오류: '앱이 시작되지 않았습니다').

문제 해결에 필요한 정보는 도움말을 참조하십시오.

 

일단 이 원인.. 잘은 모르겠지만 프로그램을 실행하는 도중에 Console 창에서 오류가 나는걸 못 띄우니 여기에서라도 실행할 때 오류를 띄우는 것 같다. 그렇다 보니 원인도 모르겠고.. 

디버깅을 할려고 해도 처음부터 저게 떠버려서 디버깅도 할 수가 없었다..

 

아무튼 방법은 찾았는데 그냥 OpenCV dll 파일이 없어서였다.. (왜 이것 때문에.. 12시간을 고생한거지;;)

 

OpenCV VCPKG WinRT용 설치

일단 한가지 알아낸 것이 있는데 WinRT에서 OpenCV를 돌릴려면 WinRT 용으로 바꿔야하는 것 같다.

WinRT는 UWP로 뭐 돌아가는건데 VCPKG에서 UWP로 설치하는 버전이 있다.

설치는 아래처럼 하면 된다.

vcpkg install opencv4:x64-uwp

이런식으로 설치하면 uwp 버전으로 설치가 된다.

 

오류 해결

앞에서 말했 듯이 그냥 이건 dll 파일이 없어서 생긴 오류이다. 실행에 필요한 dll 파일을 아래 경로에 붙여넣기 하면 오류가 해결된다.

<ProjectName>\x64\Release\<ProjectName>\AppX

그런데 한가지 문제가 있다.. 빌드 할 때마다 dll 파일이 사라져서 자동으로 복붙이 되게 해야하는데

이럴 때는 방법이 있다. 

 

한가지는 그냥 Visual Studio 프로젝트 파일에서 새 필터로 dll 파일 추가해서 하는 방법이 있는데 이건 비추하고..

다른 방법으로는 자동으로 복붙되게 하는 것이다.

 

일단 프로젝트 파일을 오른쪽 클릭하고 속성을 열어서 나오는 창에서

빌드 이벤트의 빌드 후 이벤트로 들어간다.

들어가게 되면 명령줄이 있는데 여기에 코드만 넣으면 된다.

 

일단 빌드 후 이벤트는 말그대로 빌드가 된 후에 자동으로 명령줄에 있는걸 실행하게 되는 것이다.

 

코드는 이걸 넣으면 된다!

xcopy /y "$(OutDir)\*.dll" "$(OutDir)\AppX"

일단 내가 대충 만들어서 해봤을 때 되는 코드이니.. 이게 잘 되는 코드인지는 모르겠다만.. 아무튼 난 저걸 명령줄에 넣어서 했더니 자동으로 복붙이 되었고 해결이 되었다.

 

코드는 대충 AppX에는 dll이 없지만 다행이도 출력 폴더에는 dll 파일이 있다. 그래서 모든 dll 파일을 가지고 AppX 폴더로 붙여 넣는 코드이다.

 

아무튼 이걸로 해결!

반응형
반응형

OpenCV와 Dlib로 프로젝트를 제작 중에..

기이한 현상이 발견됬다..

 

cv::Mat CVImage = dlib::toMat(DlibImage);
cv::cvtColor(CVImage, CVImage, cv::COLOR_RGB2BGR);

여기에서 저 2개의 명령어를 본다면.. 첫번째 명령어는 DlibImage를 OpenCV의 Mat 이미지인 CVImage로 바꾸는데..

보통 이렇게 바꾸면 RGB 이미지가 CVImage에 할당이 된다..

그런데 내 프로젝트가 전체적으로 BGR이다 보니깐.. RGB를 BGR로 변환을 해야해서 cvtColor로 RGB에서 BGR로 바꾸는 명령어를 쳐서 실행했는데..

 

이상하게 첫번째에 실행하면 괜찮다가.. 두번째에 실행하니깐 RGB가 RGB로 출력되는 것이다..

이유는 잘은 모르겠지만.. cvtColor가 오류를 일으켰거나 RGB와 BGR이 서로 할당되고 그러면서 충돌이 일어난 것 같다.. 난 cvtColor에 문제가 있는 것 같다 생각은 든다..

 

즉 실행하면 실행할 수록 BGR > RGB > BGR > RGB > BGR 이런식으로 계속 번갈아가며 출력되는 것..

 

그래서 내가 해결한 방법은.. 애초부터 RGB이미지를 안쓰기로 해서.. 그냥 이미지 변환안하고 바로 썼다..

그러니깐 잘된다..

 

으음..

아직도 뭔 문제인지 모르겠다.. RG를 BGR로 바꿀때의 문제들은 해외 커뮤니티에서 보긴 했는데..

 

내 OpenCV 버전이 낮아서 그런건가.. 그래도 최신껄로 깔았는데.. 뭐가 문제인건지..

 

해결했던 방법..

그냥 RGB 안쓰고 애초에 처음부터 BGR로 되게 작업..

반응형
반응형

프로젝트 제작중에 

cv::Mat A, B;
A = B;

이렇게 B의 이미지 데이터를 A로 넘기는걸 써봤다..

근데 문제가 생긴다..

 

나중에 A의 이미지를 다른걸로 바꾸면 B가 이상하게 바뀐다는 것이다..

분명 B의 이미지를 A로 넘기는 것 밖에 안했는데 바뀌는..

 

그래서 ChatGPT에 물어보니 이미지 데이터를 보내는게 아니고 참조를 한다고 한다.. 대충 A와 B는 같은 메모리를 사용하게 하는 그런건가..? 암튼 저렇게 하면 A가 B의 이미지 데이터를 참조하도록 되기 때문에.. A를 바꾸면 B가 같이 바뀌는 것이였다.. 으으

 

그래서 해결 방법은 2가지가 있는데

cv::Mat A, B;
A.copyTo(B);

이렇게 하는 방법이 있다. A의 이미지 데이터를 B로 넘긴다는 뜻!

또 다른 방법은

cv::Mat A, B;
B = A.clone();

A의 이미지를 복제해서 B로 넣는 것..

 

근데 난 의미상으론 복사를 써야하기 때문에.. 첫번째 방법으로 썼다..

암튼 끝!

반응형
반응형

일단 바로 제작된 결과!

음 얼굴을 찾아서 뭔가 하는 프로젝트를 하는데 문제가 생겼다. 얼굴 이미지를 벡터로 변환하는 과정에서 원본 이미지와 얼굴 이미지를 보여줄려 하는데 여기에서 원본 이미지를 보여줄 때 보여주는 곳이 정사각형이다..

근데 OpenCV에서 이미지를 바로 넣을려니깐 이미지를 리사이즈 해서 바로 넣는 것은 좀 불편하고.. 이미지를 정사각형에 맞춰 그냥 리사이즈 하면 이미지가 뭉개지고..

 

그래서 생각한건 흰 배경 중심에 이미지를 넣는 것인데

이걸 해결하기 위해 1시간 반이 걸렸다..

대충 생각을 해본건 

  • 원본 이미지 보여주는 곳과 같은 크기의 배경을 만들어 중앙에 이미지를 배치
  • 원본 이미지의 가장 긴 변의 길이 대로 정사각형 배경을 만들어 중앙에 이미지를 배치

이런거고 중앙에다 배치할땐

  • 비율에 맞춰 원본 이미지를 축소해서 정사각형 배경의 반에 원본 이미지의 짧은 변의 반을 빼서 위치 구하기
  • 정사각형 배경의 반에 원본 이미지의 짧은 변의 반을 빼서 위치 구하기

등을 생각했는데.. 난 여러가지 방법을 생각해보고 여러가지 방법을 해보다가 헷갈리기도 하고 수정하기도 하며 결국엔

원본 이미지의 가장 긴 변의 길이 대로 정사각형 배경을 만들어 중앙에 이미지를 배치할 때 정사각형 배경의 반에 원본 이미지의 짧은 변의 반을 빼서 위치를 구해서 바로 넣는 방법을 하기로 결정했다..

 

그래서 이걸 대충 이미지로 표시하면!

 

이런식으로 

일단 정사각형이면 그냥 패스

가로가 더 길 경우 가로 길이에 대한 정사각형을 만들고 그게 검은색 사각형!

거기에 빨간색이 원본 이미지꺼..

그래서 파란색 동그라미 부분의 위치를 구하는건데

 

검은색 사각형에서 반을 나누고 거기에서 빨간색 사각형의 반을 빼면 저 위치가 나올 것 같다 라는 생각이 들어서 한 것!

파란색은 반대로 생각하면 되는거!

 

대충 식은

(Square / 2) - (OriginalImg / 2)

뭐 어쨌든 이런 방법으로 코드를 구현한 결과!

 

if (I_celeb_img.nc() == I_celeb_img.nr())
    GUICon::putWebcamView(I_celeb_img, preSetImage);
else {
    int squareLen = (I_celeb_img.nc() < I_celeb_img.nr() ? I_celeb_img.nr() : I_celeb_img.nc());

    cv::Mat originalViewImage(squareLen, squareLen, CV_8UC3);
    originalViewImage = cv::Scalar(0xFF, 0xFF, 0xFF);

    //배경 이미지 중앙에 사진 넣기
    //사진의 세로가 가로보다 짧을 경우 squareLen의 길이에서 반을 나누고 이미지 세로의 반 만큼 빼서 좌표 구하기						
    if (I_celeb_img.nr() < I_celeb_img.nc()) { //가로가 더 클 경우 같을 경우 비교 안하는건 위에서 이미 해서
        int ypos = (squareLen / 2) - (I_celeb_img.nr() / 2); //세로가 짧을 경우 정사각형의 한 변의 길에서 이미지 세로 반을 빼서 위치 구하는 것
        CPputImage(I_celeb_img, originalViewImage, cv::Rect(0, ypos, I_celeb_img.nc(), I_celeb_img.nr()));
    }
    else {
        int xpos = (squareLen / 2) - (I_celeb_img.nc() / 2); //위와 반대
        CPputImage(I_celeb_img, originalViewImage, cv::Rect(xpos, 0, I_celeb_img.nc(), I_celeb_img.nr()));
    }
    cv::cvtColor(originalViewImage, originalViewImage, cv::COLOR_RGB2BGR);
    GUICon::putWebcamView(originalViewImage, preSetImage);
}

코드는 이렇다!

여기에서 CPputImage는 그냥 OpenCV 이미지의 특정 위치에 이미지를 넣는 함수고

GUICon::putWebCamView는 원본 이미지 표시하는 쪽에 이미지 넣는 함수다.. 암튼 그럼!

 

그럼 끝!

반응형
반응형

아마 글꼴을 찾는데 문제가 있을 수 있습니다 "맑은 고딕"은 정상적으로 작동되지만 컴퓨터마다 다를 수 있을 것 같습니다. 될 수도 있고 안 될 수도 있다는 점.. 안된다면.. 폰트 쪽 코드를 수정하면 될지도..?

 

일단 음.. 이걸 성공하게 된건.. 한국어나 영어로 찾아볼 땐 아무리 찾아도 안나왔는데.. 일본에는 전문가들이 많으니깐 있지 않을까해서 일본어로 검색해보니.. 역시 있었다. 그래서 해결하게 됨

 

바로 가져갈 분은 맨 아래쪽에 있어요.

 

https://jitaku.work/it/category/image-processing/opencv/write_japanese/

 

C++のOpenCVで日本語をputTextする

Top 作成日: 2020.06.29 C++のOpenCVで日本語をputTextする Pythonの場合比較的容易にできる、日本語を画面描画する方法。 C++はそういったことができないので非常に困っていた。 で、ネットからパク

jitaku.work

일단 나는 여기 것을 사용했는데. 여기에 있는 코드를 바로 쓰면 당연히 안될꺼다.

HFONT hFont = ::CreateFontA(
        fontSize, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE,
        SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
        VARIABLE_PITCH | FF_ROMAN, fontname);

코드를 보면 이런데.. 저기 아래 SHIFTJIS_CHARSET 저것때문에 안된다. 아마 인코딩 문제 같은데 뭐 저거를 다른 대부분 언어도 되게 할려면 DEFAULT_CHARSET으로 하면 아마 될 것 같다. 당연 한국어도 됨!

 

일단 저걸로 하면 되고

추가적으로 수정한 것

일단 내 프로젝트에선 좀 중요하기 때문에 얘를 그냥 출력하면 안티에일리어싱이 결국엔 안된다.

위의 코드에서 안티에일리어싱을 키면 되는데 킨다 하더라도 코드 때문에 결국은 안된다.

 

일단 이 코드의 방식을 보면 먼저 MFC로 어디선가?에서 적을 OpenCV Mat에서의 가로 길이만큼의 텍스트 이미지를 생성한 후 가져와서 비트맵을 Mat 방식대로 바꿔서 적용하는 방식이다. (아마 맞을꺼임)

 

근데 저기 코드를 대충 보면

if (_tmp[0] == 0 && _tmp[1] == 0 && _tmp[2] == 0) {
                    _img[0] = (unsigned char)color.val[0];
                    _img[1] = (unsigned char)color.val[1];
                    _img[2] = (unsigned char)color.val[2];
                }

이런 코드가 있다. 그리고 위쪽에 보면 back_color로 0x99가 정의 되어 있는데.. 이걸 보면 대충 알 수 있다. 일단 MFC에서 텍스트 이미지를 생성하면 텍스트 밖은 기본적으로 흰색(255, 255, 255), 텍스트는 검은색(0, 0, 0)이다.이다. 또한 0x99는 153으로 RGB 153 153 153 뭐 이래보면 회색이다. 최대가 255이니.. 그래서 최종적으로 저 코드는 텍스트외의 배경 (153, 153, 153)과 (255, 255, 255) 부분을 제외한 검은색 부분(텍스트 부분)을 가져와 사전에 정의한 RGB색대로 다시 설정하는 방식이다.

 

이 때문에 이 코드에선 아무리 안티에일리어싱을 한들.. 안티 에일리어싱이 픽셀 사이사이에 텍스트보다 연한 색을 찍는건데 이 것들이 다 제외되면서 결국엔 안티 에일리어싱이 안찍힌다..

 

그래서 내가 생각한 방식은 안티 에일리어싱의 경우 연한 색도 처리해야하기 때문에 배경색이 바뀔때마다 당연히 글자 색도 변경될테니 배경색을 직접 지정하고 텍스트 색도 직접 지정해서 나중에 배경색만 빼는 것이다. 그러면 결국엔 적용되는건 텍스트의 진한 픽셀부터 연한 픽셀까지이다. 그래서 이 방법으로 코딩한건 뭐 아래에 넣을꺼고

 

또한 내가 지정한 것 중에 다른 것들도 있지만 ori가 있다. 내가 당시 했을때 오리엔테이션인가 뭔가 하는걸로 줄여서 적은 것 같은데.. 잘 못 지정한 것 같다.

어쨌든 저 코드를 보면

int posX = (ori == 0 ? org.x : (ori == 1 ? org.x - (size.cx / 2) : org.x - size.cx)); //기준이 왼쪽이면 그대로, 중간이면 기준점 - 넓이 / 2, 오른쪽이면 기준점 - 넓이

대충 이렇게 적어놨다. 조건연산자로 이리저리 해놨는데 주석문을 보면 대충 알 수 있다. 0이면 왼쪽 기준 1이면 중간 기준 2이면 오른쪽 기준

말 그대로다. 사전에 정의한 글자 위치대로 0이면 텍스트의 맨 왼쪽 기준으로 텍스트가 생성되고 1이면 텍스트의 중간으로 생성 2이면 텍스트의 오른쪽 끝으로 생성된다.

 

그리고 세로 축도 할려했는데.. 음..! 이 때 당시엔 필요가 없었어서.. 하실 분들은 직접 하시길! 내가 기억하기론 세로는 맨 위쪽 기준으로 되는걸로 알고 있다.

 

코드를 보면 뭐 배경색 칠하는 것도 있고 텍스트 색 지정하는 것도 있고 그렇다.. 어쨌든 그런거임!

 

이제 코드를 보여줌!

코드

void _putText(cv::Mat& img, const cv::String& text, const cv::Point& org, const int ori, const char* fontname, const int fontWeight, const double fontScale, const bool anti, const RGBScale textcolor, const RGBScale bkcolor) {
	int fontSize = (int)(10 * fontScale);
	int width = img.cols;
	int height = fontSize * 3 / 2;

	HDC hdc = CreateCompatibleDC(NULL);

	HBRUSH hBrush = CreateSolidBrush(bkcolor.rgb);

	RECT rect;
	rect.left = rect.top = 0;
	rect.right = width;
	rect.bottom = height;

	BITMAPINFOHEADER header;
	ZeroMemory(&header, sizeof(BITMAPINFOHEADER));
	header.biSize = sizeof(BITMAPINFOHEADER);
	header.biWidth = width;
	header.biHeight = height;
	header.biPlanes = 1;
	header.biBitCount = 24;
	BITMAPINFO bitmapInfo;
	bitmapInfo.bmiHeader = header;
	HBITMAP hbmp = CreateDIBSection(NULL, (LPBITMAPINFO)&bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0);
	SelectObject(hdc, hbmp);

	FillRect(hdc, &rect, hBrush);

	BITMAP  bitmap;
	GetObject(hbmp, sizeof(BITMAP), &bitmap);

	HFONT hFont = CreateFontA(
		fontSize,
		0,
		0,
		0,
		fontWeight,
		FALSE,
		FALSE,
		FALSE,
		DEFAULT_CHARSET,
		OUT_DEFAULT_PRECIS, //SHIFTJIS_CHARSET -> DEFAULT_CHARSET으로 변경
		CLIP_DEFAULT_PRECIS,
		(anti ? ANTIALIASED_QUALITY : DEFAULT_QUALITY), //안티를 허용하면 해주고 아니면 안해주고
		VARIABLE_PITCH | FF_ROMAN,
		fontname);
	SelectObject(hdc, hFont);
	SetTextColor(hdc, textcolor.rgb);
	SetBkColor(hdc, bkcolor.rgb);

	//넓이 높이 구하기
	SIZE size;
	GetTextExtentPoint32A(hdc, text.c_str(), (int)text.length(), &size);

	TextOutA(hdc, 0, height / 3 * 1, text.c_str(), (int)text.length());
	int posX = (ori == 0 ? org.x : (ori == 1 ? org.x - (size.cx / 2) : org.x - size.cx)); //기준이 왼쪽이면 그대로, 중간이면 기준점 - 넓이 / 2, 오른쪽이면 기준점 - 넓이
	int posY = org.y - (size.cy / 2 + 5);

	unsigned char* _tmp;
	unsigned char* _img;
	for (int y = 0; y < bitmap.bmHeight; y++) {
		if (posY + y >= 0 && posY + y < img.rows) {
			_img = img.data + (int)(3 * posX + (posY + y) * (((bitmap.bmBitsPixel / 8) * img.cols) & ~3));
			_tmp = (unsigned char*)(bitmap.bmBits) + (int)((bitmap.bmHeight - y - 1) * (((bitmap.bmBitsPixel / 8) * bitmap.bmWidth) & ~3));
			for (int x = 0; x < bitmap.bmWidth; x++) {
				if (x + posX >= img.cols) {
					break;
				}

				if (_tmp[0] != bkcolor.b || _tmp[1] != bkcolor.g || _tmp[2] != bkcolor.r) { //순서를 bgr를 써서 bgr로 한거, rgb 순서이면 그걸로 해야함
					_img[0] = (unsigned char)_tmp[0];
					_img[1] = (unsigned char)_tmp[1];
					_img[2] = (unsigned char)_tmp[2];
				}
				_img += 3;
				_tmp += 3;
			}
		}
	}

	DeleteObject(hFont);
	DeleteObject(hbmp);
	DeleteDC(hdc);
}

주석문 보고 뭐 대충 하면 될 것 같다. 난 OPENCV의 기본 MAT의 설정인 BGR때문에 아래가 BGR 기준이고 RGB면 순서를 바꿔서 작성해야 할 것이다.

 

cv::Mat& img, const cv::String& text, const cv::Point& org, const int ori, const char* fontname, const int fontWeight, const double fontScale, const bool anti, const RGBScale textcolor, const RGBScale bkcolor

파라미터를 대충 설명하면

  • cv::Mat& img -> 텍스트를 적용할 이미지
  • cv::String& text -> 출력할 텍스트
  • cv::Point& org -> OpenCV 이미지에서 텍스트를 지정할 위치
  • int ori -> 텍스트 위치를 지정할 때 왼쪽 중앙 오른쪽으로 어느 위치로 정렬해서 출력할지
  • char* fontname -> 폰트 이름 (예: 맑은 코딕)
  • int fontWeight -> 글자의 굵기 (예: FW_BOLD 이런거 하면 됨.. 그냥 숫자로 해도 되고)
  • double fontScale -> 글자 크기 (예: 이건 좀 보정을 안했는데 그냥 무조건 큰 숫자 적으면 진짜 커지므로 기본 생각했던 것보다 반 작게 줄여서 적으면 아마 맞을꺼다)
  • bool anti -> 안티에일리어싱을 할꺼냐 말꺼냐
  • RGBScale textcolor -> 텍스트의 컬러 지정 (예: RGBScale(255, 0, 0))
  • RGBScale bkcolor -> 배경색 지정 (예: RGBScale(255, 255, 255))

어쨌든 이정도다.. 뭐 쓰다보니 파라미터가 너무 많아지긴 했지만.. 뭐 내가 쓰는건데 뭐 어때!

_putText(outImg, "나", cvPoint(50, 50), 1, "맑은 고딕", FW_BOLD, 6, true, RGBScale(0, 0, 0), RGBScale(255, 255, 255));

사용 예시는 위와 같다.

 

어쨌든 그렇다. 이거 글 쓰는 것도 힘들 구 생각하는 것도 힘들었는데..

나중에 자기 글에다 쓰고 싶다면... 적어도 링크라도.. 부탁.. (이거 그럼 만든게 2022년 11월 쯤에 만들었으니.. 고등학교 2학년 때 만든거군.. 아 여기 학교 C/C++과목 전혀 없음)

 

뭐 어쨌든 끄읕!

 

얼마나 사용해줄진 모르겠지만.. C++은 겁나 복잡해!!

 

(파이썬은 짧고 쉽던데.. 방식은 이거와 비슷)

 

2023-03-01 추가

코드에서 RGBScale에 대한 구조체 내용이 없어서 다시 정리하고 구조체에 대한 것도 새로 적습니다.

struct RGBScale {
    int r = 0;
    int g = 0;
    int b = 0;
    int rgb = 0;

    RGBScale(int r, int g, int b) {
        this->r = r;
        this->g = g;
        this->b = b;

        this->rgb = RGB(r, g, b);
    }
};

RGBScale(0xFF, 0xFF, 0xFF)로 적으면 되는데 0xFF는 그냥 16진수 이기 때문에 0부터 255 숫자중 원하는 색깔에 맞춰 적으시면 됩니다! 그리고.. 기본적으로 cv::Mat 생성할 때 RGB가 아닌 BGR로 생성하기 때문에 아마 RGB 이미지를 넣어서 적용시키면 색깔이 다르게 나올꺼기 때문에.. 인풋엔 BGR로 넣으시면 됩니다. 수정할려면 아래 적혀있는 코드에서 비트맵을 OpenCV로 바꿔주는 곳에서 b, g, r 적혀있는 것을 r, g, b로 변경하시면 될겁니다. RGBScale를 따로 만든 이유는 그냥 r, g, b도 추출하고 rgb도 출력하고 하기 위함!

 

아래는 다시 정리해본 코드!

void CPputText(cv::Mat& O_image, cv::String text, cv::Point org, int ori, const char* fontName, int fontWeight, double fontScale, RGBScale textColor, RGBScale bkColor) {
	int fontSize = (int)(10 * fontScale);
	int width = O_image.cols;
	int height = fontSize * 3 / 2;

	HDC hdc = CreateCompatibleDC(NULL); //텍스트 이미지를 만들어두는 곳 같은거

	HBRUSH hBrush = CreateSolidBrush(bkColor.rgb); //채우는 방식인데 bkColor로 단색으로 채우는거

	//텍스트 이미지 크기 정하는거
	RECT rect;
	rect.left = rect.top = 0;
	rect.right = width;
	rect.bottom = height;

	//비트맵의 구조를 사전에 정의하는 것 크기나 색
	BITMAPINFOHEADER header;
	ZeroMemory(&header, sizeof(BITMAPINFOHEADER));
	header.biSize = sizeof(BITMAPINFOHEADER);
	header.biWidth = width;
	header.biHeight = height;
	header.biPlanes = 1;
	header.biBitCount = 24;
	BITMAPINFO bitmapInfo;
	bitmapInfo.bmiHeader = header;
	HBITMAP hbmp = CreateDIBSection(NULL, (LPBITMAPINFO)&bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0);
	SelectObject(hdc, hbmp); //hdc에 적용? 하는 거

	FillRect(hdc, &rect, hBrush); //지정한 크기만큼 완전하게 채우는거 (다 채움)

	BITMAP bitmap;
	GetObject(hbmp, sizeof(BITMAP), &bitmap);

	//텍스트 이미지 만들 때 사용할 수 있는 폰트를 생성? 하는 그런거
	HFONT hFont = CreateFontA(
		fontSize,
		0,
		0,
		0,
		fontWeight,
		FALSE,
		FALSE,
		FALSE,
		DEFAULT_CHARSET, //한국어나 일본어나 해주게 하는거 (아마)
		OUT_DEFAULT_PRECIS,
		CLIP_DEFAULT_PRECIS,
		ANTIALIASED_QUALITY, //안티 에일리어싱을 켜주는거
		VARIABLE_PITCH | FF_ROMAN,
		fontName);
	SelectObject(hdc, hFont);
	SetTextColor(hdc, textColor.rgb);
	SetBkColor(hdc, bkColor.rgb);

	//계산을 위해 미리 텍스트의 사이즈 구하는거
	SIZE size;
	GetTextExtentPoint32A(hdc, text.c_str(), (int)text.length(), &size);

	TextOutA(hdc, 0, height / 3 * 1, text.c_str(), (int)text.length()); //이미지에 텍스트 적는거
	int posX = (ori == 0 ? org.x : (ori == 1 ? org.x - (size.cx / 2) : org.x - size.cx)); //기준 정하는거 0은 텍스트의 왼쪽 1은 텍스트의 중간 2는 텍스트의 오른쪽
	int posY = org.y - (size.cy / 2 + 5);

	//비트맵 사진을 OpenCV이미지에 삽입해주는거
	unsigned char* _tmp;
	unsigned char* _img;
	for (int y = 0; y < bitmap.bmHeight; y++) {
		if (posY + y >= 0 && posY + y < O_image.rows) {
			_img = O_image.data + (int)(3 * posX + (posY + y) * (((bitmap.bmBitsPixel / 8) * O_image.cols) & ~3));
			_tmp = (unsigned char*)(bitmap.bmBits) + (int)((bitmap.bmHeight - y - 1) * (((bitmap.bmBitsPixel / 8) * bitmap.bmWidth) & ~3));
			for (int x = 0; x < bitmap.bmWidth; x++) {
				if (x + posX >= O_image.cols)
					break;

				if (_tmp[0] != bkcolor.b || _tmp[1] != bkcolor.g || _tmp[2] != bkcolor.r) { //텍스트 이미지의 배경 컬러는 없애기 위한 것, bgr 순서로 하는 이유는 Mat 이미지를 처음에 만들 때 BGR 순이여서
					_img[0] = (unsigned char)_tmp[0]; //B
					_img[1] = (unsigned char)_tmp[1]; //G
					_img[2] = (unsigned char)_tmp[2]; //R
				}
				_img += 3;
				_tmp += 3;
			}
		}
	}

	//메모리에서 삭제해주는거 이거 안하면 메모리 계속 사용함
	DeleteObject(hBrush);
	DeleteObject(hFont);
	DeleteObject(hbmp);
	DeleteObject(hdc);
}
cv::Mat inputMat(500, 500, CV_8UC3);
CPputText(inputMat, "안녕!", cvPoint(inputMat.cols / 2, inputMat.rows), 1, "맑은 고딕", FW_BOLD, 6, RGBScale(0xFF, 0xFF, 0xFF), RGBScale(0, 0, 0));

아아마 이렇게 하면 500 * 500 으로 이미지를 생성하고 그 중간에 텍스트를 넣는거니 완전 중간은 아니고.. 세로가 좀 아래로 쳐져있긴 하지만.. 저렇게 하면 잘 작동은 합니다!

반응형
반응형

학교에서 프로젝트를 받아버려서.. 해야하는 상황..

내 프로젝트를 위해선 DLIB와 OPENCV가 필요한데..

정말 2~3일동안 수없이 도전해보다가 굉장히 간단한 방법을 찾아서 알려줄까함! (왜이리 dlib는 잘 안깔리는거야)

 

일단 설치 방법은 요약하면 VCPKG를 설치해서 DLIB와 OPENCV를 설치하면 된다!

이미 VCPKG가 깔려있다면 2번으로 넘어가주세요.

1. VCPKG 설치하기

설치는 아래 링크로 들어가서 보시면 되겠습니다~~

https://cheongpark.tistory.com/15

 

윈도우에서 VCPKG 설치하기

VCPKG는 대충 C++ 그런거의 패키지를 자동으로 설치해주는? 느낌인 것 같다.. 자동화로 설치해줘서 짜증나는 오류들을 경험하지 않고 빠르게 설치해주는 엄청난 놈인 것 같다! VCPKG 설치하기 https://

cheongpark.tistory.com

 

2. dlib와 opencv 설치

vcpkg install dlib:x64-windows
vcpkg install opencv:x64-windows

위 명령어를 커맨드 창에 입력해주세요!

만약 vcpkg가 없는 명령어로 뜨면 환경 변수 설정이 안되거나 환경 변수 경로를 잘 못 지정했을 겁니다!

x64-windows는 vcpkg 패키지 리스트에서 보고 자기꺼에 맞는 걸로 선택하시면 됩니다!

 

이렇게 하면 모든 것이 설치 완료!!

이제 Visual Studio에서 include에서 사용하시면 됩니다!

// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
/*

    This is an example illustrating the use of the perspective_window tool
    in the dlib C++ Library.  It is a simple tool for displaying 3D point 
    clouds on the screen.

*/

#include <dlib/gui_widgets.h>
#include <dlib/image_transforms.h>
#include <cmath>

using namespace dlib;
using namespace std;

// ----------------------------------------------------------------------------------------

int main()
{
    // Let's make a point cloud that looks like a 3D spiral.
    std::vector<perspective_window::overlay_dot> points;
    dlib::rand rnd;
    for (double i = 0; i < 20; i+=0.001)
    {
        // Get a point on a spiral
        dlib::vector<double> val(sin(i),cos(i),i/4);

        // Now add some random noise to it
        dlib::vector<double> temp(rnd.get_random_gaussian(),
                                  rnd.get_random_gaussian(),
                                  rnd.get_random_gaussian());
        val += temp/20;

        // Pick a color based on how far we are along the spiral
        rgb_pixel color = colormap_jet(i,0,20);

        // And add the point to the list of points we will display
        points.push_back(perspective_window::overlay_dot(val, color));
    }

    // Now finally display the point cloud.
    perspective_window win;
    win.set_title("perspective_window 3D point cloud");
    win.add_overlay(points);
    win.wait_until_closed();
}

//  ----------------------------------------------------------------------------

위 소스는 dlib.net의 기본 예제입니다.

위 소스를 Visual Studio에서 빈 프로젝트로 하나 만들고 소스 파일에서 test.cpp 하나 만들고 위 코드를 입력해서 실행해보시면 아주 잘 되는 것을 알 수 있습니다!

이런식으로 창이 나오면 잘 작동한다는 것이죠!

마우스로 회전도 되더라구요.. (그래프로 만들면 재밌겠다)

 

뭐 어쨌든 이 방식으로 설치했다면 빌드 폴더에 dll 파일도 나오는 경우가 있는데 이걸 같이 이동 시켜줘야지 다른 컴퓨터에서도 정상적으로 작동할 겁니다! (아무것도 설치 안되어있어도 잘 작동하더라구요.. 뭐 다른 한개는 설치해줘야 하긴 하는데..)

 

찾아보니 x64-windows-static 버전은 exe에다가 dll 파일 연결 안하고 모조리 다 때려 넣는 것 같군요! 하지만 설정은 더 힘드니 저 혼자만 하도록 하죠!

 

다만 맥이나 리눅스에서는 안될지도?

 

어쨌든 이만 끝!

VCPKG는 진짜 엄청나다..!

 

반응형

'설치 > C++' 카테고리의 다른 글

Visual Studio 자동 완성 규칙 변경  (0) 2024.01.25
VCPKG 버전 업데이트  (0) 2024.01.08
윈도우에서 VCPKG 설치하기  (0) 2022.11.06
반응형

Windows로 OpenCV를 CMake로 빌드할 때

이런식으로 여러가지 오류가 뜬다!

(하하.. 이것 때문에 MSYS도 깔고 그랬는데도 안됬었다..)

 

제일 큰 문제는 저런식으로 Cannot copy output executable, Recorded try_compile output location doesn't exist:

이런식으로 여러가지 뜨는 문제는 아마도 버전 문제인 것 같다...

 

3.25.0 rc3 버전으로 깔아서 Configure을 눌르면 저런 오류들 뜨면서 안된다..

 

위와 말했던 것 처럼 이건 버전 오류인 것 같고..

3.24.2버전이나 그 아래 버전으로 새로 다운받아서 설치하면 정상적으로 Configure(설정)이 된다..!

 

(학교에서 프로젝트 숙제를 받아서 노트북을 새로 빌리고 (교사용으로) 새로 필요한거 빌드 하고 있었는데 하하하.. 이젠 다른걸 빌드 해야한다..)

새로 다운받아서 하니 이렇게 오류는 전혀 안뜸!

 

요약

이런 식의 오류가 나오면 현재 버전을 지우고 그 아래 버전으로 다운 받아서 새로 설치 후 다시 설정해보시길 바랍니다~~

반응형

+ Recent posts