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++
101 lines
3.7 KiB
C++
#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();
|
|
}
|
|
}
|