要实现您描述的效果,即在不旋转图片的情况下达到类似旋转、绘制、再旋转回正常角度的效果,我们需要通过计算网格和圆心的位置来模拟这些旋转。具体实现中,将网点沿指定的角度排列,而不是简单地根据图像的行列直接绘制网点。
以下是实现思路的代码:
#include <opencv2/opencv.hpp>
#include <cmath>
// 根据角度计算网格调整后的圆心
cv::Point2f calculateRotatedCenter(int x, int y, int blockSize, double angleRad, const cv::Point2f& center) {
double cosA = std::cos(angleRad);
double sinA = std::sin(angleRad);
int dx = x - center.x;
int dy = y - center.y;
float newX = dx * cosA - dy * sinA + center.x;
float newY = dx * sinA + dy * cosA + center.y;
return cv::Point2f(newX, newY);
}
void drawHalftone(cv::Mat& image, int blockSize, double angle) {
double angleRad = angle * CV_PI / 180.0;
cv::Point2f center(image.cols / 2.0f, image.rows / 2.0f);
for (int y = 0; y < image.rows; y += blockSize) {
for (int x = 0; x < image.cols; x += blockSize) {
// 计算网格的中心
cv::Point2f originalCenter(x + blockSize / 2.0f, y + blockSize / 2.0f);
cv::Point2f rotatedCenter = calculateRotatedCenter(originalCenter.x, originalCenter.y, blockSize, -angleRad, center);
// 确保在图像范围内
if (rotatedCenter.x >= 0 && rotatedCenter.y >= 0 &&
rotatedCenter.x < image.cols && rotatedCenter.y < image.rows) {
// 提取原图的块并计算平均灰度值
cv::Rect blockRect(x, y, blockSize, blockSize);
cv::Mat block = image(blockRect);
double avgGray = cv::mean(block)[0];
double radius = (avgGray / 255.0) * (blockSize / 2.0);
// 绘制圆形
cv::circle(image, rotatedCenter, static_cast<int>(radius), cv::Scalar(0), -1);
}
}
}
}
int main() {
// 读取图像
cv::Mat image = cv::imread("input.jpg", cv::IMREAD_GRAYSCALE);
if (image.empty()) {
std::cerr << "读取图像失败!" << std::endl;
return -1;
}
int blockSize = 10; // 网格块的大小
double angle = 45; // 要模拟旋转的角度
drawHalftone(image, blockSize, angle);
// 显示结果
cv::imshow("Halftone", image);
cv::waitKey(0);
return 0;
}
请确保替换 `"input.jpg"` 为实际图片路径。这段代码通过对网格的位置进行旋转计算,然后在相应的位置绘制圆点,从而模拟了旋转图片再画圆点的效果。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 |