要实现不旋转图片的情况下模拟任何角度的半色调效果并控制特定灰度范围内的点绘制,可以通过调整网点的排列,以及对灰度值进行控制。这里是调整后的代码:
#include <opencv2/opencv.hpp>
#include <iostream>
void drawHalftone(cv::Mat& image, int blockSize, double angle) {
double angleRad = angle * CV_PI / 180.0;
double cosA = std::cos(angleRad);
double sinA = std::sin(angleRad);
cv::Mat result = cv::Mat::ones(image.size(), image.type()) * 255; // 创建白色的结果图像
int halfBlock = blockSize / 2;
// 使用偏移计算旋转后的点位置
for (int y = 0; y < image.rows; y += blockSize) {
for (int x = 0; x < image.cols; x += blockSize) {
int shiftedX = x + (y / blockSize) * blockSize * sinA; // 根据行偏移
int shiftedY = y - (x / blockSize) * blockSize * sinA; // 根据列偏移
// 确保网格中心在图像范围内
if (shiftedX >= 0 && shiftedY >= 0 && shiftedX + blockSize < image.cols && shiftedY + blockSize < image.rows) {
cv::Rect blockRect(x, y, blockSize, blockSize);
cv::Mat block = image(blockRect);
double avgGray = cv::mean(block)[0];
if (avgGray <= 7) {
cv::rectangle(result, cv::Point(x, y), cv::Point(x + blockSize, y + blockSize), cv::Scalar(0), cv::FILLED);
} else if (avgGray >= 253) {
cv::rectangle(result, cv::Point(x, y), cv::Point(x + blockSize, y + blockSize), cv::Scalar(255), cv::FILLED);
} else {
double radius = (avgGray / 255.0) * halfBlock;
cv::circle(result, cv::Point(shiftedX + halfBlock, shiftedY + halfBlock), static_cast<int>(radius), cv::Scalar(0), cv::FILLED);
}
}
}
}
image = result; // 将结果图像返回
}
int main() {
cv::Mat image = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);
if (image.empty()) {
std::cerr << "无法加载图像!" << std::endl;
return -1;
}
drawHalftone(image, 10, 45); // 调整 blockSize 和 angle 为所需值
cv::imwrite("output.jpg", image); // 保存结果图像
return 0;
}
这个代码:
1. **设置初始图像为白色**:以便在特定灰度范围进行条件填充。
2. **根据网点位置进行水平和垂直偏移调整**:模拟网点角度。
3. **使用圆圈绘制控制**:根据灰度区间控制黑白显示和灰度范围内的圆点绘制。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |