123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- #include "pch.h"
- #include "cvUtil.h"
- int getWhitePixNumber(cv::Mat& img) {
- int w = img.cols;
- int h = img.rows;
- int total = 0;
- for (int i = 0; i < h; i++) {
- uchar* p2 = img.ptr<uchar>(i);
- for (int j = 0; j < w; j++) {
- uchar& pix = *p2++;
- if (pix == 255)
- total++;
- }
- }
- return total;
- }
- // 按照指定长款缩放图像
- cv::Mat scaleImage(int w, int h, cv::Mat& image)
- {
- // 获取原始图像的宽度和高度
- int originalWidth = image.cols;
- int originalHeight = image.rows;
- // 计算缩放比例
- double scaleRatio = 1.0;
- if (w > 0 && h > 0)
- {
- // 如果指定了宽度和高度,计算宽度和高度的缩放比例并选择较小值作为最终缩放比例
- double widthRatio = static_cast<double>(w) / originalWidth;
- double heightRatio = static_cast<double>(h) / originalHeight;
- scaleRatio = std::min(widthRatio, heightRatio);
- }
- else if (w > 0)
- {
- // 如果指定了宽度,根据宽度计算缩放比例
- scaleRatio = static_cast<double>(w) / originalWidth;
- }
- else if (h > 0)
- {
- // 如果指定了高度,根据高度计算缩放比例
- scaleRatio = static_cast<double>(h) / originalHeight;
- }
- // 计算缩放后的新宽度和新高度
- int newWidth = static_cast<int>(originalWidth * scaleRatio);
- int newHeight = static_cast<int>(originalHeight * scaleRatio);
- // 执行缩放操作
- cv::Mat scaledImage;
- cv::resize(image, scaledImage, cv::Size(newWidth, newHeight));
- return scaledImage;
- }
- cv::Mat paddingResize(cv::Mat& image, int w, int h) {
- int originalWidth = image.cols;
- int originalHeight = image.rows;
- // 计算缩放比例
- float scale = std::min(static_cast<float>(w) / originalWidth, static_cast<float>(h) / originalHeight);
- int newWidth = static_cast<int>(originalWidth * scale);
- int newHeight = static_cast<int>(originalHeight * scale);
- // 创建一个新的画布,大小为指定的宽度和高度,填充为白色
- cv::Mat paddedImage(h, w, image.type(), cv::Scalar(255, 255, 255));
- // 计算填充后的图像在新画布上的位置
- int x = (w - newWidth) / 2;
- int y = (h - newHeight) / 2;
- // 调整图像大小并将其放置在新画布上
- cv::resize(image, image, cv::Size(newWidth, newHeight));
- image.copyTo(paddedImage(cv::Rect(x, y, newWidth, newHeight)));
- return paddedImage;
- }
- cv::Mat paddingNoResize(cv::Mat& image, int w, int h) {
- int originalWidth = image.cols;
- int originalHeight = image.rows;
- // 创建一个新的画布,大小为指定的宽度和高度,填充为白色
- cv::Mat paddedImage(h, w, image.type(), cv::Scalar(255, 255, 255));
- // 计算填充后的图像在新画布上的位置
- int x = (w - originalWidth) / 2;
- int y = (h - originalHeight) / 2;
- // 调整图像大小并将其放置在新画布上
- image.copyTo(paddedImage(cv::Rect(x, y, originalWidth, originalHeight)));
- return paddedImage;
- }
- cv::Mat splitAndInsertImages(const cv::Mat& imageA, const cv::Mat& imageB) {
- int w = imageB.cols;
- int h = imageB.rows;
- // 创建目标图像,大小为imageB
- cv::Mat targetImage = imageB.clone();
- // 计算imageB四等分的大小
- int quarterW = w / 2;
- int quarterH = h / 2;
- // 将imageA放入四等分的每一块内
- cv::Mat roi1 = targetImage(cv::Rect(0, 0, quarterW, quarterH));
- cv::Mat roi2 = targetImage(cv::Rect(quarterW, 0, quarterW, quarterH));
- cv::Mat roi3 = targetImage(cv::Rect(0, quarterH, quarterW, quarterH));
- cv::Mat roi4 = targetImage(cv::Rect(quarterW, quarterH, quarterW, quarterH));
- imageA.copyTo(roi1);
- imageA.copyTo(roi2);
- imageA.copyTo(roi3);
- imageA.copyTo(roi4);
- return targetImage;
- }
- std::vector<cv::Rect> getAllBoundingBoxes(const cv::Mat& img)
- {
- std::vector<cv::Rect> vecBoxes;
- cv::Mat labels, stats, centroids, img_color, img_gray;
- int nccomps = cv::connectedComponentsWithStats(img, labels, stats, centroids);
- for (int i = 1; i < nccomps; i++) {
- int l = stats.at<int>(i, cv::CC_STAT_LEFT);
- int t = stats.at<int>(i, cv::CC_STAT_TOP);
- int w = stats.at<int>(i, cv::CC_STAT_WIDTH);
- int h = stats.at<int>(i, cv::CC_STAT_HEIGHT);
- vecBoxes.push_back(cv::Rect(l, t, w, h));
- }
- return vecBoxes;
- }
- std::vector<Cluster> clusterRectangles(const std::vector<cv::Rect>& rectangles)
- {
- std::vector<Cluster> clusters;
- std::vector<bool> processed(rectangles.size(), false);
- for (int i = 0; i < rectangles.size(); ++i)
- {
- if (processed[i])
- continue;
- Cluster cluster;
- cluster.rect = rectangles[i];
- cluster.indices.push_back(i);
- processed[i] = true;
- for (int j = i + 1; j < rectangles.size(); ++j)
- {
- if (processed[j])
- continue;
- int overlapHeight = std::min(cluster.rect.y + cluster.rect.height, rectangles[j].y + rectangles[j].height) - std::max(cluster.rect.y, rectangles[j].y);
- if (overlapHeight > 0)
- {
- cluster.rect |= rectangles[j];
- cluster.indices.push_back(j);
- processed[j] = true;
- }
- }
- clusters.push_back(cluster);
- }
- return clusters;
- }
- // 闭运算 丢弃 输入 黑底白字图像
- void colseImg(const cv::Mat& lpImgSrc, cv::Mat& lpImgDes, cv::Size sizeErode)
- {
- sizeErode.width = sizeErode.width - sizeErode.width % 3;
- sizeErode.height = sizeErode.height - sizeErode.height % 3;
- if (0 == sizeErode.width % 2)
- sizeErode.width += 3;
- if (0 == sizeErode.height % 2)
- sizeErode.height += 3;
- cv::Mat element = getStructuringElement(cv::MORPH_RECT, sizeErode);
- morphologyEx(lpImgSrc, lpImgDes, cv::MORPH_OPEN, element);
- }
- // 开运算 连通白色块 输入 黑底白字图像 这个运算内核必须能被2和3整除 否则会有像素平移情况发生
- void openImg(const cv::Mat& lpImgSrc, cv::Mat& lpImgDes, cv::Size sizeErode)
- {
- sizeErode.width = sizeErode.width - sizeErode.width % 3;
- sizeErode.height = sizeErode.height - sizeErode.height % 3;
- if (0 == sizeErode.width % 2)
- sizeErode.width += 3;
- if (0 == sizeErode.height % 2)
- sizeErode.height += 3;
- cv::Mat element = getStructuringElement(cv::MORPH_RECT, sizeErode);
- morphologyEx(lpImgSrc, lpImgDes, cv::MORPH_CLOSE, element);
- }
- void rectangleMask(cv::Mat& image, const cv::Rect& box, int alpha, bool useRandColor /*= true*/, const cv::Scalar& color /* = cv::Scalar()*/)
- {
- if (image.empty()) {
- std::cerr << "Input image is empty." << std::endl;
- return;
- }
- if (alpha < 0 || alpha > 100) {
- std::cerr << "Alpha value should be between 0 and 100." << std::endl;
- return;
- }
- // 生成随机颜色
- cv::Scalar maskColor;
- if (useRandColor){
- maskColor = cv::Scalar(rand() % 256, rand() % 256, rand() % 256);
- }
- else {
- maskColor = color;
- }
- cv::Mat mask(box.size(), CV_8UC3, maskColor);
- cv::Mat roi = image(box);
- cv::addWeighted(roi, (100 - alpha) / 100.0, mask, alpha / 100.0, 0, roi);
- }
- void adjustBoundingBox(int imageWidth, int imageHeight, cv::Rect& box)
- {
- // 获取图像的宽度和高度
- //int imageWidth = image.cols;
- //int imageHeight = image.rows;
- // 确保矩形框的left在图像内
- if (box.x < 0)
- box.x = 0;
- // 确保矩形框的right在图像内
- if (box.x + box.width > imageWidth)
- box.width = imageWidth - box.x;
- // 确保矩形框的top在图像内
- if (box.y < 0)
- box.y = 0;
- // 确保矩形框的bottom在图像内
- if (box.y + box.height > imageHeight)
- box.height = imageHeight - box.y;
- }
- void adjustBoundingBox(const cv::Mat& image, cv::Rect& box) {
- int imageWidth = image.cols;
- int imageHeight = image.rows;
- adjustBoundingBox(imageWidth, imageHeight, box);
- }
- void printText(const cv::Mat& image, const cv::Point& pos, const std::string& text, int height, int width )
- {
- // 设置字体类型和大小
- int fontFace = cv::FONT_HERSHEY_SIMPLEX;
- double fontScale = height / 40.0;
- // 根据给定的宽度调整字体大小
- if (width != 0)
- {
- int textWidth = 0;
- int textHeight = 0;
- // 测量文字的宽度和高度
- cv::Size textSize = cv::getTextSize(text, fontFace, fontScale, 1, &textHeight);
- // 根据给定的宽度调整字体大小
- while (textSize.width > width && fontScale > 0)
- {
- fontScale -= 0.1;
- textSize = cv::getTextSize(text, fontFace, fontScale, 1, &textHeight);
- }
- }
- // 在图像上绘制文字
- cv::putText(image, text, pos, fontFace, fontScale, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
- }
- double boxSimIOU(cv::Rect boxA, cv::Rect boxB)
- {
- cv::Rect intersection = boxA & boxB;
- double intersectionArea = intersection.area();
- double boxAArea = boxA.area();
- if (boxAArea == 0.0)
- // Handle the case where boxA has zero area
- return 0.0;
- else {
- double iou = intersectionArea / boxAArea;
- return iou;
- }
- }
- double boxVerProjectionSimIOU(cv::Rect boxA, cv::Rect boxB) {
- // 计算两个矩形的 Y 轴投影的重叠区域
- int startY = std::max(boxA.y, boxB.y);
- int endY = std::min(boxA.y + boxA.height-1, boxB.y + boxB.height-1);
- // 计算两个区域的高度(重叠部分)
- int intersectionHeight = std::max(0, endY - startY);
- if (intersectionHeight <= 0)
- return 0.0;
- // 计算两个矩形的总高度(并集部分)
- int unionHeight = boxA.height + boxB.height - intersectionHeight;
- double iou = static_cast<double>(intersectionHeight) / unionHeight;
- return iou;
- }
|