You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

101 lines
3.7 KiB
C++

2 months ago
#include "image_utilities.h"
#include <opencv2/imgproc.hpp>
#include <vector>
#include <cmath>
#include <iostream>
#include <exception>
using namespace std;
vector<cv::Point> mrect2box(const cv::RotatedRect& mrect) {
cv::Point2f boxPoints[4];
mrect.points(boxPoints);
vector<cv::Point> result;
for (int i = 0; i < 4; ++i) {
result.emplace_back(cv::Point(static_cast<int>(boxPoints[i].x), static_cast<int>(boxPoints[i].y)));
}
return result;
}
cv::Mat block_threshold(const cv::Mat& gray) {
try {
int height = gray.rows;
int width = gray.cols;
vector<int> divisions = {8, 13};
vector<int> block_sizes;
for (int div : divisions) {
int size = max(19, (height + width) / 2 / div);
if (size % 2 == 0) size++;
block_sizes.push_back(size);
}
vector<pair<int, int>> block_strategies;
for (int size : block_sizes) {
block_strategies.push_back({size, 0});
block_strategies.push_back({size, size / 2});
}
cv::Mat otsu;
double global_threshold = cv::threshold(gray, otsu, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
cv::Mat adaptive_ref;
cv::adaptiveThreshold(gray, adaptive_ref, 255, cv::ADAPTIVE_THRESH_GAUSSIAN_C, cv::THRESH_BINARY_INV, block_sizes[0], 20);
cv::Mat result = cv::Mat::zeros(gray.size(), CV_8UC1);
for (auto& strategy : block_strategies) {
int block_size = strategy.first;
int offset = strategy.second;
cv::Mat current_result = cv::Mat::zeros(gray.size(), CV_8UC1);
for (int y = offset; y < height; y += block_size) {
for (int x = offset; x < width; x += block_size) {
int end_y = min(y + block_size, height);
int end_x = min(x + block_size, width);
cv::Mat block_roi = gray(cv::Rect(x, y, end_x - x, end_y - y));
cv::Scalar mean, stddev;
cv::meanStdDev(block_roi, mean, stddev);
double variance = stddev[0] * stddev[0];
cv::Mat block_result;
if (variance < 80) {
block_result = cv::Mat::zeros(block_roi.size(), CV_8UC1);
if (mean[0] < global_threshold) {
block_result = cv::Mat::ones(block_roi.size(), CV_8UC1) * 255;
}
} else {
cv::threshold(block_roi, block_result, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);
cv::Scalar ref_mean, block_mean;
cv::Mat adaptive_block = adaptive_ref(cv::Rect(x, y, end_x - x, end_y - y));
cv::meanStdDev(adaptive_block, ref_mean, cv::noArray());
cv::meanStdDev(block_result, block_mean, cv::noArray());
if (abs(ref_mean[0] - block_mean[0]) > 200) {
block_result = 255 - block_result;
}
}
block_result.copyTo(current_result(cv::Rect(x, y, end_x - x, end_y - y)));
}
}
cv::bitwise_or(result, current_result, result);
}
return result;
} catch (const exception& e) {
cout << "Exception in block_threshold: " << e.what() << endl;
return cv::Mat();
} catch (...) {
cout << "Unknown exception in block_threshold" << endl;
return cv::Mat();
}
}