|
|
您遇到了数组越界错误。让我提供一个完全修正的版本,解决所有问题并添加LPI控制:
- #include <opencv2/opencv.hpp>
- #include <vector>
- #include <cmath>
- using namespace cv;
- using namespace std;
- const int N = 64; // 矩阵尺寸
- const float PI = 3.14159265358979323846f;
- // 生成平滑的圆形网点阈值矩阵
- vector<vector<int>> createCircularDotMatrix(int size, float gamma) {
- vector<vector<int>> matrix(size, vector<int>(size));
- float center = (size - 1) / 2.0f;
- float maxDist = size / 2.0f;
-
- for (int i = 0; i < size; i++) {
- for (int j = 0; j < size; j++) {
- float dx = i - center;
- float dy = j - center;
- float distance = sqrt(dx*dx + dy*dy);
- float normalized = distance / maxDist;
-
- // 使用伽马校正控制网点形状
- float smoothValue = 1.0f - normalized;
- smoothValue = pow(smoothValue, gamma);
-
- // 确保中心阈值高,边缘阈值低
- int threshold = static_cast<int>(smoothValue * 255);
- matrix[i][j] = threshold;
- }
- }
- return matrix;
- }
- // 检查是否为纯色文字边缘
- bool isSolidTextEdge(const vector<Mat>& cmykChannels, int x, int y, int width, int height) {
- if (x < 0 || x >= width || y < 0 || y >= height) return false;
-
- // 检查所有通道
- for (int c = 0; c < 4; c++) {
- uchar pixelValue = cmykChannels[c].at<uchar>(y, x);
- // 如果是灰色(非纯色)
- if (pixelValue > 10 && pixelValue < 245) {
- // 检查周围2像素内是否有纯色像素
- for (int dy = -2; dy <= 2; dy++) {
- for (int dx = -2; dx <= 2; dx++) {
- int nx = x + dx;
- int ny = y + dy;
- if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
- uchar neighborValue = cmykChannels[c].at<uchar>(ny, nx);
- // 如果邻居是纯色(纯黑或纯白)
- if (neighborValue <= 10 || neighborValue >= 245) {
- return true;
- }
- }
- }
- }
- }
- }
- return false;
- }
- // 半色调通道处理函数
- void halftoneChannel(Mat& input, Mat& output, float angle, const vector<vector<int>>& dotMatrix,
- float dotSpacing, int channelIndex, const vector<Mat>& cmykChannels) {
- int width = input.cols;
- int height = input.rows;
-
- // 计算旋转后的网格坐标
- float cos_angle = cos(angle);
- float sin_angle = sin(angle);
-
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- // 检查是否为纯色文字边缘
- if (isSolidTextEdge(cmykChannels, x, y, width, height)) {
- // 保留原色
- output.at<uchar>(y, x) = input.at<uchar>(y, x);
- continue;
- }
-
- uchar pixelValue = input.at<uchar>(y, x);
-
- // 处理纯色(0%或100%)
- if (pixelValue <= 10) { // 纯白
- output.at<uchar>(y, x) = 255;
- continue;
- }
- if (pixelValue >= 245) { // 纯黑
- output.at<uchar>(y, x) = 0;
- continue;
- }
-
- // 计算在旋转网格中的位置
- float u = x * cos_angle + y * sin_angle;
- float v = -x * sin_angle + y * cos_angle;
-
- // 计算网格单元内的相对位置
- int i = static_cast<int>(fmod(u, dotSpacing) / dotSpacing * N);
- int j = static_cast<int>(fmod(v, dotSpacing) / dotSpacing * N);
-
- // 确保索引在有效范围内
- i = max(0, min(N-1, i));
- j = max(0, min(N-1, j));
-
- int threshold = dotMatrix[i][j];
-
- // 关键修正:正确的网点逻辑
- if (pixelValue < threshold) {
- output.at<uchar>(y, x) = 0; // 黑色网点
- } else {
- output.at<uchar>(y, x) = 255; // 白色背景
- }
- }
- }
- }
- // 主函数
- void convertToHalftone(vector<Mat>& cmykChannels, vector<Mat>& outputChannels,
- float lpi, int dpi) {
- // 计算网点间距(像素)
- float dotSpacing = dpi / lpi;
-
- // 定义角度(弧度)
- vector<float> angles = {
- 15.0f * PI / 180.0f, // C - 15度
- 75.0f * PI / 180.0f, // M - 75度
- 0.0f, // Y - 0度
- 45.0f * PI / 180.0f // K - 45度
- };
-
- // 创建网点矩阵(使用伽马=1.5获得更平滑的过渡)
- vector<vector<int>> dotMatrix = createCircularDotMatrix(N, 1.5f);
-
- // 处理每个通道
- for (int i = 0; i < 4; i++) {
- outputChannels[i] = Mat::zeros(cmykChannels[i].size(), CV_8UC1);
- halftoneChannel(cmykChannels[i], outputChannels[i], angles[i],
- dotMatrix, dotSpacing, i, cmykChannels);
- }
- }
复制代码
这个修正版本:
1. 解决了数组越界问题
2. 添加了LPI控制(通过dotSpacing参数)
3. 使用更大的矩阵(N=64)获得更平滑的网点
4. 添加了伽马校正控制网点形状
5. 保持了正确的网点逻辑(浅色小网点,深色大网点)
6. 正确处理文字边缘
要控制LPI,您需要在调用convertToHalftone函数时指定LPI值和DPI值。例如,对于80 LPI和300 DPI:
- convertToHalftone(cmykChannels, outputChannels, 80.0f, 300.0f);
复制代码
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |
|