#include "AlgCommon.h" //保护rect边界,防止越界访问造成程序崩溃 bool protectRect(cv::Rect& rect, int width, int height) { if (width == 0 || height == 0) { return false; } rect.x = std::max(rect.x, 0); rect.x = std::min(rect.x, width - 1); rect.y = std::max(rect.y, 0); rect.y = std::min(rect.y, height - 1); int right = rect.x + rect.width; int bottom = rect.y + rect.height; right = std::max(right, 0); right = std::min(right, width - 1); bottom = std::max(bottom, 0); bottom = std::min(bottom, height - 1); rect.width = std::max(right - rect.x, 0); rect.height = std::max(bottom - rect.y, 0); if (rect.width == 0 || rect.height == 0) return false; return true; } void GetStringSize(HDC hDC, const char* str, int* w, int* h) { SIZE size; GetTextExtentPoint32A(hDC, str, strlen(str), &size); if (w != 0) *w = size.cx; if (h != 0) *h = size.cy; } void putTextZH(cv::Mat& dst, const char* str, cv::Point org, cv::Scalar color, int fontSize, const char* fn, bool italic, bool underline) { CV_Assert(dst.data != 0 && (dst.channels() == 1 || dst.channels() == 3)); int x, y, r, b; if (org.x > dst.cols || org.y > dst.rows) return; x = org.x < 0 ? -org.x : 0; y = org.y < 0 ? -org.y : 0; LOGFONTA lf; lf.lfHeight = -fontSize; lf.lfWidth = 0; lf.lfEscapement = 0; lf.lfOrientation = 0; lf.lfWeight = 5; lf.lfItalic = italic; //斜体 lf.lfUnderline = underline; //下划线 lf.lfStrikeOut = 0; lf.lfCharSet = DEFAULT_CHARSET; lf.lfOutPrecision = 0; lf.lfClipPrecision = 0; lf.lfQuality = PROOF_QUALITY; lf.lfPitchAndFamily = 0; strcpy_s(lf.lfFaceName, fn); HFONT hf = CreateFontIndirectA(&lf); HDC hDC = CreateCompatibleDC(0); HFONT hOldFont = (HFONT)SelectObject(hDC, hf); int strBaseW = 0, strBaseH = 0; int singleRow = 0; char buf[1 << 12]; strcpy_s(buf, str); char* bufT[1 << 12]; // 这个用于分隔字符串后剩余的字符,可能会超出。 //处理多行 { int nnh = 0; int cw, ch; const char* ln = strtok_s(buf, "\n", bufT); while (ln != 0) { GetStringSize(hDC, ln, &cw, &ch); strBaseW = std::max(strBaseW, cw); strBaseH = std::max(strBaseH, ch); ln = strtok_s(0, "\n", bufT); nnh++; } singleRow = strBaseH; strBaseH *= nnh; } if (org.x + strBaseW < 0 || org.y + strBaseH < 0) { SelectObject(hDC, hOldFont); DeleteObject(hf); DeleteObject(hDC); return; } r = org.x + strBaseW > dst.cols ? dst.cols - org.x - 1 : strBaseW - 1; b = org.y + strBaseH > dst.rows ? dst.rows - org.y - 1 : strBaseH - 1; org.x = org.x < 0 ? 0 : org.x; org.y = org.y < 0 ? 0 : org.y; BITMAPINFO bmp = { 0 }; BITMAPINFOHEADER& bih = bmp.bmiHeader; int strDrawLineStep = strBaseW * 3 % 4 == 0 ? strBaseW * 3 : (strBaseW * 3 + 4 - ((strBaseW * 3) % 4)); bih.biSize = sizeof(BITMAPINFOHEADER); bih.biWidth = strBaseW; bih.biHeight = strBaseH; bih.biPlanes = 1; bih.biBitCount = 24; bih.biCompression = BI_RGB; bih.biSizeImage = strBaseH * strDrawLineStep; bih.biClrUsed = 0; bih.biClrImportant = 0; void* pDibData = 0; HBITMAP hBmp = CreateDIBSection(hDC, &bmp, DIB_RGB_COLORS, &pDibData, 0, 0); CV_Assert(pDibData != 0); HBITMAP hOldBmp = (HBITMAP)SelectObject(hDC, hBmp); //color.val[2], color.val[1], color.val[0] SetTextColor(hDC, RGB(255, 255, 255)); SetBkColor(hDC, 0); //SetStretchBltMode(hDC, COLORONCOLOR); strcpy_s(buf, str); const char* ln = strtok_s(buf, "\n", bufT); int outTextY = 0; while (ln != 0) { TextOutA(hDC, 0, outTextY, ln, strlen(ln)); outTextY += singleRow; ln = strtok_s(0, "\n", bufT); } uchar* dstData = (uchar*)dst.data; int dstStep = dst.step / sizeof(dstData[0]); unsigned char* pImg = (unsigned char*)dst.data + org.x * dst.channels() + org.y * dstStep; unsigned char* pStr = (unsigned char*)pDibData + x * 3; for (int tty = y; tty <= b; ++tty) { unsigned char* subImg = pImg + (tty - y) * dstStep; unsigned char* subStr = pStr + (strBaseH - tty - 1) * strDrawLineStep; for (int ttx = x; ttx <= r; ++ttx) { for (int n = 0; n < dst.channels(); ++n) { double vtxt = subStr[n] / 255.0; int cvv = vtxt * color.val[n] + (1 - vtxt) * subImg[n]; subImg[n] = cvv > 255 ? 255 : (cvv < 0 ? 0 : cvv); } subStr += 3; subImg += dst.channels(); } } SelectObject(hDC, hOldBmp); SelectObject(hDC, hOldFont); DeleteObject(hf); DeleteObject(hBmp); DeleteDC(hDC); } void putTextCorner(cv::Mat& image, std::string text, cv::Scalar color, int where) { //设置绘制文本的相关参数 int x_margin = 25; int y_margin = 25; int font_face = cv::FONT_HERSHEY_COMPLEX; double font_scale = 1.5; int thickness = 2; int baseline; //获取文本框的长宽 cv::Size text_size = cv::getTextSize(text, font_face, font_scale, thickness, &baseline); //将文本框居中绘制 cv::Point origin; switch (where) { case 1: //左上 origin.x = x_margin; origin.y = y_margin; break; case 2: //右上 origin.x = image.cols - x_margin - text_size.width; origin.y = y_margin; break; case 3: //左下 origin.x = x_margin; origin.y = image.rows - y_margin; break; case 4: //右下 origin.x = image.cols - x_margin - text_size.width; origin.y = image.rows - y_margin; break; default: origin.x = image.cols / 2 - text_size.width / 2; origin.y = image.rows / 2 + text_size.height / 2; break; } cv::putText(image, text, origin, font_face, font_scale, color, thickness, 8, false); } void fistEROthenDIL(cv::Mat& input,uint8_t EROsize,uint8_t DILsize) { cv::Mat element_erode, element_dilate; if (EROsize) { element_erode = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(EROsize, EROsize)); cv::erode(input, input, element_erode); } if (DILsize) { element_dilate = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(DILsize, DILsize)); cv::dilate(input, input, element_dilate); } } void fistDILthenERO(cv::Mat& input, uint8_t DILsize, uint8_t EROsize) { cv::Mat element_erode, element_dilate; if (DILsize) { element_dilate = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(DILsize, DILsize)); cv::dilate(input, input, element_dilate); } if (EROsize) { element_erode = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(EROsize, EROsize)); cv::erode(input, input, element_erode); } } bool isInside(cv::Rect rect1, cv::Rect rect2) { return (rect1 == (rect1&rect2)); } cv::Point getCenterPoint(cv::Rect rect) { cv::Point cpt; cpt.x = rect.x + cvRound(rect.width / 2.0); cpt.y = rect.y + cvRound(rect.height / 2.0); return cpt; } cv::Rect rectCenterScale(cv::Rect rect, cv::Size size) { rect = rect + size; cv::Point pt; pt.x = cvRound(size.width / 2.0); pt.y = cvRound(size.height / 2.0); return (rect - pt); } uchar minimum(uchar a, uchar b) { return a <= b ? a : b; } cv::Mat rgb2cmyk(cv::Mat& rgb) { cv::Mat cmyk = cv::Mat::zeros(rgb.rows, rgb.cols, CV_8UC4); int pixel_num = rgb.rows * rgb.cols; for (int i = 0; i < pixel_num; i++) { uchar c = 255 - rgb.data[3 * i + 0]; uchar m = 255 - rgb.data[3 * i + 1]; uchar y = 255 - rgb.data[3 * i + 2]; uchar K = minimum(minimum(c, m), y); uchar C = 0; uchar M = 0; uchar Y = 0; if (K == 255) { C = 0; M = 0; Y = 0; } else { C = (uchar)((c - K)*255.0 / (255 - K)); M = (uchar)((m - K)*255.0 / (255 - K)); Y = (uchar)((y - K)*255.0 / (255 - K)); } cmyk.data[4 * i + 0] = C; cmyk.data[4 * i + 1] = M; cmyk.data[4 * i + 2] = Y; cmyk.data[4 * i + 3] = K; } return cmyk; } bool sort_rect_by_x_center(cv::Rect r1, cv::Rect r2) { return (r1.x + r1.width / 2) < (r2.x + r2.width / 2); } bool sort_rect_by_y_center(cv::Rect r1, cv::Rect r2) { return (r1.y + r1.height / 2) < (r2.y + r2.height / 2); } bool sort_rect_by_height(cv::Rect r1, cv::Rect r2) { return (r1.height) < (r2.height); } bool sort_rect_by_width(cv::Rect r1, cv::Rect r2) { return (r1.width) < (r2.width); }