96 lines
3.2 KiB
C++
96 lines
3.2 KiB
C++
#pragma once
|
||
#include <opencv.hpp>
|
||
|
||
#pragma region 画叉
|
||
static void Cross(cv::Mat& image, const cv::Point& center, int length, int thickness, const cv::Scalar& color = cv::Scalar(255, 255, 255)) {
|
||
// 检查输入图像是否有效
|
||
if (image.empty()) {
|
||
throw std::invalid_argument("Input image is empty");
|
||
}
|
||
|
||
// 计算水平和垂直线段的起点和终点
|
||
cv::Point horizontalStart(center.x - length / 2, center.y);
|
||
cv::Point horizontalEnd(center.x + length / 2, center.y);
|
||
cv::Point verticalStart(center.x, center.y - length / 2);
|
||
cv::Point verticalEnd(center.x, center.y + length / 2);
|
||
|
||
// 绘制水平和垂直线段
|
||
cv::line(image, horizontalStart, horizontalEnd, color, thickness);
|
||
cv::line(image, verticalStart, verticalEnd, color, thickness);
|
||
}
|
||
#pragma endregion
|
||
|
||
#pragma region 写中文
|
||
static std::wstring utf8ToWstring(const std::string& utf8Str) {
|
||
int len = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, nullptr, 0);
|
||
if (len == 0) return L"";
|
||
std::wstring wstr(len, L'\0');
|
||
MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, &wstr[0], len);
|
||
wstr.pop_back(); // remove null terminator
|
||
return wstr;
|
||
}
|
||
// 在图像上绘制中文(仅 Windows,使用 GDI)
|
||
static void putTextZH(cv::Mat& image, const std::string& text, cv::Point org, int fontSize = 20, cv::Scalar color = cv::Scalar(255, 0, 0)) {
|
||
// 创建兼容的位图
|
||
cv::Mat img;
|
||
if (image.channels() == 1)
|
||
cv::cvtColor(image, img, cv::COLOR_GRAY2BGRA);
|
||
else if (image.channels() == 3)
|
||
cv::cvtColor(image, img, cv::COLOR_BGR2BGRA);
|
||
else if (image.channels() == 4)
|
||
img = image.clone();
|
||
else
|
||
throw std::runtime_error("Unsupported number of channels");
|
||
|
||
// 创建 Windows 位图信息
|
||
HDC hdc = GetDC(nullptr);
|
||
HDC memDC = CreateCompatibleDC(hdc);
|
||
BITMAPINFO bmi;
|
||
memset(&bmi, 0, sizeof(BITMAPINFO));
|
||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||
bmi.bmiHeader.biWidth = img.cols;
|
||
bmi.bmiHeader.biHeight = -img.rows; // top-down
|
||
bmi.bmiHeader.biPlanes = 1;
|
||
bmi.bmiHeader.biBitCount = 32;
|
||
bmi.bmiHeader.biCompression = BI_RGB;
|
||
|
||
void* pBits = nullptr;
|
||
HBITMAP hBitmap = CreateDIBSection(memDC, &bmi, DIB_RGB_COLORS, &pBits, nullptr, 0);
|
||
SelectObject(memDC, hBitmap);
|
||
memcpy(pBits, img.data, img.total() * img.elemSize());
|
||
|
||
// 设置字体
|
||
HFONT hFont = CreateFontW(
|
||
fontSize, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,
|
||
GB2312_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
|
||
ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_SWISS, L"微软雅黑");
|
||
SelectObject(memDC, hFont);
|
||
|
||
// 设置颜色和背景
|
||
SetBkMode(memDC, TRANSPARENT);
|
||
SetTextColor(memDC, RGB(color[2], color[1], color[0]));
|
||
|
||
// 输出文字
|
||
std::wstring wtext = utf8ToWstring(text);
|
||
TextOutW(memDC, org.x, org.y, wtext.c_str(), static_cast<int>(wtext.length()));
|
||
|
||
// 拷贝回来
|
||
GetDIBits(memDC, hBitmap, 0, img.rows, img.data, &bmi, DIB_RGB_COLORS);
|
||
|
||
// 转换回原始图像格式
|
||
if (image.channels() == 1)
|
||
cv::cvtColor(img, image, cv::COLOR_BGRA2GRAY);
|
||
else if (image.channels() == 3)
|
||
cv::cvtColor(img, image, cv::COLOR_BGRA2BGR);
|
||
else if (image.channels() == 4)
|
||
image = img.clone();
|
||
|
||
// 清理
|
||
DeleteObject(hFont);
|
||
DeleteObject(hBitmap);
|
||
DeleteDC(memDC);
|
||
ReleaseDC(nullptr, hdc);
|
||
}
|
||
#pragma endregion
|
||
|