#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
// 生成并返回一个旋转的半色调图案
void createHalftonePattern(Mat &pattern, int dotRadius, double angle) {
int size = dotRadius * 2; // 图案大小必须充足以旋转
pattern = Mat::zeros(size * 10, size * 10, CV_8UC1); // 创建一个足够大的图案矩阵
// 用于计算旋转的点中心和旋转矩阵
Point center(size, size);
Mat rotationMatrix = getRotationMatrix2D(center, angle, 1);
Mat tempPattern = Mat::zeros(size, size, CV_8UC1);
circle(tempPattern, center, dotRadius, Scalar(255), FILLED);
// 把圆点阵列用于跨越较大区域
for (int y = 0; y < pattern.rows; y += size) {
for (int x = 0; x < pattern.cols; x += size) {
Mat roi = pattern(Rect(x, y, size, size));
tempPattern.copyTo(roi);
}
}
// 对大的图案应用旋转
warpAffine(pattern, pattern, rotationMatrix, pattern.size());
}
// 应用半色调效果
void applyHalftonePattern(const Mat &src, Mat &dst, int dotRadius, double angle) {
Mat pattern;
createHalftonePattern(pattern, dotRadius, angle);
dst = src.clone();
for (int y = 0; y < src.rows; y += pattern.rows) {
for (int x = 0; x < src.cols; x += pattern.cols) {
Rect roi(x, y, pattern.cols, pattern.rows);
// 检查是否超过边界
if (x + pattern.cols > src.cols || y + pattern.rows > src.rows)
continue;
// 从源提取ROI
Mat srcRoi = src(roi);
// 创建一个小于128为黑的掩码用于对原始图像进行阈值化处理
Mat mask;
threshold(srcRoi, mask, 128, 255, THRESH_BINARY_INV);
// 复制图案以适应ROI的大小
Mat fullPattern;
pattern(Rect(0, 0, mask.cols, mask.rows)).copyTo(fullPattern);
// 使用bitwise_and提取组件
Mat dstRoi = dst(roi);
fullPattern.copyTo(dstRoi, mask);
}
}
}
int main() {
Mat img = imread("your_image_path.jpg", IMREAD_GRAYSCALE);
if (img.empty()) {
std::cerr << "Error: Cannot load image\n";
return -1;
}
Mat halftoneImg;
applyHalftonePattern(img, halftoneImg, 5, 45); // 调整dotRadius和angle以获得不同效果
imshow("Halftone Image", halftoneImg);
waitKey(0);
return 0;
}