cvUtil.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. #include "pch.h"
  2. #include "cvUtil.h"
  3. int getWhitePixNumber(cv::Mat& img) {
  4. int w = img.cols;
  5. int h = img.rows;
  6. int total = 0;
  7. for (int i = 0; i < h; i++) {
  8. uchar* p2 = img.ptr<uchar>(i);
  9. for (int j = 0; j < w; j++) {
  10. uchar& pix = *p2++;
  11. if (pix == 255)
  12. total++;
  13. }
  14. }
  15. return total;
  16. }
  17. // 按照指定长款缩放图像
  18. cv::Mat scaleImage(int w, int h, cv::Mat& image)
  19. {
  20. // 获取原始图像的宽度和高度
  21. int originalWidth = image.cols;
  22. int originalHeight = image.rows;
  23. // 计算缩放比例
  24. double scaleRatio = 1.0;
  25. if (w > 0 && h > 0)
  26. {
  27. // 如果指定了宽度和高度,计算宽度和高度的缩放比例并选择较小值作为最终缩放比例
  28. double widthRatio = static_cast<double>(w) / originalWidth;
  29. double heightRatio = static_cast<double>(h) / originalHeight;
  30. scaleRatio = std::min(widthRatio, heightRatio);
  31. }
  32. else if (w > 0)
  33. {
  34. // 如果指定了宽度,根据宽度计算缩放比例
  35. scaleRatio = static_cast<double>(w) / originalWidth;
  36. }
  37. else if (h > 0)
  38. {
  39. // 如果指定了高度,根据高度计算缩放比例
  40. scaleRatio = static_cast<double>(h) / originalHeight;
  41. }
  42. // 计算缩放后的新宽度和新高度
  43. int newWidth = static_cast<int>(originalWidth * scaleRatio);
  44. int newHeight = static_cast<int>(originalHeight * scaleRatio);
  45. // 执行缩放操作
  46. cv::Mat scaledImage;
  47. cv::resize(image, scaledImage, cv::Size(newWidth, newHeight));
  48. return scaledImage;
  49. }
  50. cv::Mat paddingResize(cv::Mat& image, int w, int h) {
  51. int originalWidth = image.cols;
  52. int originalHeight = image.rows;
  53. // 计算缩放比例
  54. float scale = std::min(static_cast<float>(w) / originalWidth, static_cast<float>(h) / originalHeight);
  55. int newWidth = static_cast<int>(originalWidth * scale);
  56. int newHeight = static_cast<int>(originalHeight * scale);
  57. // 创建一个新的画布,大小为指定的宽度和高度,填充为白色
  58. cv::Mat paddedImage(h, w, image.type(), cv::Scalar(255, 255, 255));
  59. // 计算填充后的图像在新画布上的位置
  60. int x = (w - newWidth) / 2;
  61. int y = (h - newHeight) / 2;
  62. // 调整图像大小并将其放置在新画布上
  63. cv::resize(image, image, cv::Size(newWidth, newHeight));
  64. image.copyTo(paddedImage(cv::Rect(x, y, newWidth, newHeight)));
  65. return paddedImage;
  66. }
  67. cv::Mat paddingNoResize(cv::Mat& image, int w, int h) {
  68. int originalWidth = image.cols;
  69. int originalHeight = image.rows;
  70. // 创建一个新的画布,大小为指定的宽度和高度,填充为白色
  71. cv::Mat paddedImage(h, w, image.type(), cv::Scalar(255, 255, 255));
  72. // 计算填充后的图像在新画布上的位置
  73. int x = (w - originalWidth) / 2;
  74. int y = (h - originalHeight) / 2;
  75. // 调整图像大小并将其放置在新画布上
  76. image.copyTo(paddedImage(cv::Rect(x, y, originalWidth, originalHeight)));
  77. return paddedImage;
  78. }
  79. cv::Mat splitAndInsertImages(const cv::Mat& imageA, const cv::Mat& imageB) {
  80. int w = imageB.cols;
  81. int h = imageB.rows;
  82. // 创建目标图像,大小为imageB
  83. cv::Mat targetImage = imageB.clone();
  84. // 计算imageB四等分的大小
  85. int quarterW = w / 2;
  86. int quarterH = h / 2;
  87. // 将imageA放入四等分的每一块内
  88. cv::Mat roi1 = targetImage(cv::Rect(0, 0, quarterW, quarterH));
  89. cv::Mat roi2 = targetImage(cv::Rect(quarterW, 0, quarterW, quarterH));
  90. cv::Mat roi3 = targetImage(cv::Rect(0, quarterH, quarterW, quarterH));
  91. cv::Mat roi4 = targetImage(cv::Rect(quarterW, quarterH, quarterW, quarterH));
  92. imageA.copyTo(roi1);
  93. imageA.copyTo(roi2);
  94. imageA.copyTo(roi3);
  95. imageA.copyTo(roi4);
  96. return targetImage;
  97. }
  98. std::vector<cv::Rect> getAllBoundingBoxes(const cv::Mat& img)
  99. {
  100. std::vector<cv::Rect> vecBoxes;
  101. cv::Mat labels, stats, centroids, img_color, img_gray;
  102. int nccomps = cv::connectedComponentsWithStats(img, labels, stats, centroids);
  103. for (int i = 1; i < nccomps; i++) {
  104. int l = stats.at<int>(i, cv::CC_STAT_LEFT);
  105. int t = stats.at<int>(i, cv::CC_STAT_TOP);
  106. int w = stats.at<int>(i, cv::CC_STAT_WIDTH);
  107. int h = stats.at<int>(i, cv::CC_STAT_HEIGHT);
  108. vecBoxes.push_back(cv::Rect(l, t, w, h));
  109. }
  110. return vecBoxes;
  111. }
  112. std::vector<Cluster> clusterRectangles(const std::vector<cv::Rect>& rectangles)
  113. {
  114. std::vector<Cluster> clusters;
  115. std::vector<bool> processed(rectangles.size(), false);
  116. for (int i = 0; i < rectangles.size(); ++i)
  117. {
  118. if (processed[i])
  119. continue;
  120. Cluster cluster;
  121. cluster.rect = rectangles[i];
  122. cluster.indices.push_back(i);
  123. processed[i] = true;
  124. for (int j = i + 1; j < rectangles.size(); ++j)
  125. {
  126. if (processed[j])
  127. continue;
  128. int overlapHeight = std::min(cluster.rect.y + cluster.rect.height, rectangles[j].y + rectangles[j].height) - std::max(cluster.rect.y, rectangles[j].y);
  129. if (overlapHeight > 0)
  130. {
  131. cluster.rect |= rectangles[j];
  132. cluster.indices.push_back(j);
  133. processed[j] = true;
  134. }
  135. }
  136. clusters.push_back(cluster);
  137. }
  138. return clusters;
  139. }
  140. // 闭运算 丢弃 输入 黑底白字图像
  141. void colseImg(const cv::Mat& lpImgSrc, cv::Mat& lpImgDes, cv::Size sizeErode)
  142. {
  143. sizeErode.width = sizeErode.width - sizeErode.width % 3;
  144. sizeErode.height = sizeErode.height - sizeErode.height % 3;
  145. if (0 == sizeErode.width % 2)
  146. sizeErode.width += 3;
  147. if (0 == sizeErode.height % 2)
  148. sizeErode.height += 3;
  149. cv::Mat element = getStructuringElement(cv::MORPH_RECT, sizeErode);
  150. morphologyEx(lpImgSrc, lpImgDes, cv::MORPH_OPEN, element);
  151. }
  152. // 开运算 连通白色块 输入 黑底白字图像 这个运算内核必须能被2和3整除 否则会有像素平移情况发生
  153. void openImg(const cv::Mat& lpImgSrc, cv::Mat& lpImgDes, cv::Size sizeErode)
  154. {
  155. sizeErode.width = sizeErode.width - sizeErode.width % 3;
  156. sizeErode.height = sizeErode.height - sizeErode.height % 3;
  157. if (0 == sizeErode.width % 2)
  158. sizeErode.width += 3;
  159. if (0 == sizeErode.height % 2)
  160. sizeErode.height += 3;
  161. cv::Mat element = getStructuringElement(cv::MORPH_RECT, sizeErode);
  162. morphologyEx(lpImgSrc, lpImgDes, cv::MORPH_CLOSE, element);
  163. }
  164. void rectangleMask(cv::Mat& image, const cv::Rect& box, int alpha, bool useRandColor /*= true*/, const cv::Scalar& color /* = cv::Scalar()*/)
  165. {
  166. if (image.empty()) {
  167. std::cerr << "Input image is empty." << std::endl;
  168. return;
  169. }
  170. if (alpha < 0 || alpha > 100) {
  171. std::cerr << "Alpha value should be between 0 and 100." << std::endl;
  172. return;
  173. }
  174. // 生成随机颜色
  175. cv::Scalar maskColor;
  176. if (useRandColor){
  177. maskColor = cv::Scalar(rand() % 256, rand() % 256, rand() % 256);
  178. }
  179. else {
  180. maskColor = color;
  181. }
  182. cv::Mat mask(box.size(), CV_8UC3, maskColor);
  183. cv::Mat roi = image(box);
  184. cv::addWeighted(roi, (100 - alpha) / 100.0, mask, alpha / 100.0, 0, roi);
  185. }
  186. void adjustBoundingBox(int imageWidth, int imageHeight, cv::Rect& box)
  187. {
  188. // 获取图像的宽度和高度
  189. //int imageWidth = image.cols;
  190. //int imageHeight = image.rows;
  191. // 确保矩形框的left在图像内
  192. if (box.x < 0)
  193. box.x = 0;
  194. // 确保矩形框的right在图像内
  195. if (box.x + box.width > imageWidth)
  196. box.width = imageWidth - box.x;
  197. // 确保矩形框的top在图像内
  198. if (box.y < 0)
  199. box.y = 0;
  200. // 确保矩形框的bottom在图像内
  201. if (box.y + box.height > imageHeight)
  202. box.height = imageHeight - box.y;
  203. }
  204. void adjustBoundingBox(const cv::Mat& image, cv::Rect& box) {
  205. int imageWidth = image.cols;
  206. int imageHeight = image.rows;
  207. adjustBoundingBox(imageWidth, imageHeight, box);
  208. }
  209. void printText(const cv::Mat& image, const cv::Point& pos, const std::string& text, int height, int width )
  210. {
  211. // 设置字体类型和大小
  212. int fontFace = cv::FONT_HERSHEY_SIMPLEX;
  213. double fontScale = height / 40.0;
  214. // 根据给定的宽度调整字体大小
  215. if (width != 0)
  216. {
  217. int textWidth = 0;
  218. int textHeight = 0;
  219. // 测量文字的宽度和高度
  220. cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, 1, &textHeight);
  221. // 根据给定的宽度调整字体大小
  222. while (textSize.width > width && fontScale > 0)
  223. {
  224. fontScale -= 0.1;
  225. textSize = cv::getTextSize(text, fontFace, fontScale, 1, &textHeight);
  226. }
  227. }
  228. // 在图像上绘制文字
  229. cv::putText(image, text, pos, fontFace, fontScale, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
  230. }
  231. double boxSimIOU(cv::Rect boxA, cv::Rect boxB)
  232. {
  233. cv::Rect intersection = boxA & boxB;
  234. double intersectionArea = intersection.area();
  235. double boxAArea = boxA.area();
  236. if (boxAArea == 0.0)
  237. // Handle the case where boxA has zero area
  238. return 0.0;
  239. else {
  240. double iou = intersectionArea / boxAArea;
  241. return iou;
  242. }
  243. }
  244. double boxVerProjectionSimIOU(cv::Rect boxA, cv::Rect boxB) {
  245. // 计算两个矩形的 Y 轴投影的重叠区域
  246. int startY = std::max(boxA.y, boxB.y);
  247. int endY = std::min(boxA.y + boxA.height-1, boxB.y + boxB.height-1);
  248. // 计算两个区域的高度(重叠部分)
  249. int intersectionHeight = std::max(0, endY - startY);
  250. if (intersectionHeight <= 0)
  251. return 0.0;
  252. // 计算两个矩形的总高度(并集部分)
  253. int unionHeight = boxA.height + boxB.height - intersectionHeight;
  254. double iou = static_cast<double>(intersectionHeight) / unionHeight;
  255. return iou;
  256. }