gpt4 book ai didi

c++ - 用渐变填充圆圈

转载 作者:太空狗 更新时间:2023-10-29 19:47:43 25 4
gpt4 key购买 nike

我想要用渐变颜色填充圆圈,就像我在底部显示的那样。我想不出简单的方法,如何做到这一点。我可以画更多的圈,但过渡是可见的。

cv::circle(img, center, circle_radius * 1.5, cv::Scalar(1.0, 1.0, 0.3), CV_FILLED);
cv::circle(img, center, circle_radius * 1.2, cv::Scalar(1.0, 1.0, 0.6), CV_FILLED);
cv::circle(img, center, circle_radius, cv::Scalar(1.0, 1.0, 1.0), CV_FILLED);

enter image description here

最佳答案

您需要做的就是创建一个函数,该函数接受一个中心点和一个新点,计算距离,并返回该点的灰度值。或者,您可以只返回距离,将 距离 存储在该点,然后稍后使用 cv::normalize() 缩放整个距离。

假设您在 (100, 100) 图像中将中心点设置为 (50, 50)。这是您想要执行的操作的伪代码:

function euclideanDistance(center, point)  # returns a float
return sqrt( (center.x - point.x)^2 + (center.y - point.y)^2 )

center = (50, 50)
rows = 100
cols = 100

gradient = new Mat(rows, cols) # should be of type float

for row < rows:
for col < cols:
point = (col, row)
gradient[row, col] = euclideanDistance(center, point)

normalize(gradient, 0, 255, NORM_MINMAX, uint8)
gradient = 255 - gradient

注意这里的步骤:

  1. 创建欧氏距离函数来计算距离
  2. 创建一个浮点矩阵来保存距离值
  3. 遍历所有行和列并分配一个距离值
  4. 归一化到你想要的范围(你可以在这里坚持使用 float 而不是转换为 uint8,但你做到了)
  5. 翻转二元梯度,因为越远的距离会越亮——但你想要相反的结果。

现在,对于您的确切示例图像,圆圈中有渐变,而此方法只是将整个图像创建为渐变。在你的情况下,如果你想要一个特定的半径,只需修改计算欧几里德距离的函数,如果它超出一定距离,将其设置为 0(圆心的值,最终将翻转为白色) :

function euclideanDistance(center, point, radius)  # returns a float
distance = sqrt( (center.x - point.x)^2 + (center.y - point.y)^2 )
if distance > radius:
return 0
else
return distance

下面是实际的 C++ 代码:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <cmath>

float euclidean_distance(cv::Point center, cv::Point point, int radius){
float distance = std::sqrt(
std::pow(center.x - point.x, 2) + std::pow(center.y - point.y, 2));
if (distance > radius) return 0;
return distance;
}

int main(){

int h = 400;
int w = 400;
int radius = 100;
cv::Mat gradient = cv::Mat::zeros(h, w, CV_32F);

cv::Point center(150, 200);
cv::Point point;

for(int row=0; row<h; ++row){
for(int col=0; col<w; ++col){
point.x = col;
point.y = row;
gradient.at<float>(row, col) = euclidean_distance(center, point, radius);
}
}

cv::normalize(gradient, gradient, 0, 255, cv::NORM_MINMAX, CV_8U);
cv::bitwise_not(gradient, gradient);

cv::imshow("gradient", gradient);
cv::waitKey();

}

Gradient image


一个完全不同的方法(尽管做同样的事情)是使用 distanceTransform() .这个函数将白色 Blob 的中心到最近的黑色值的距离映射到灰度值,就像我们上面做的那样。这段代码更简洁并且做了同样的事情。但是,它可以处理任意形状,而不仅仅是圆形,这很酷。

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

int main(){

int h = 400;
int w = 400;
int radius = 100;
cv::Point center(150, 200);
cv::Mat gradient = cv::Mat::zeros(h, w, CV_8U);
cv::rectangle(gradient, cv::Point(115, 100), cv::Point(270, 350), cv::Scalar(255), -1, 8 );

cv::Mat gradient_padding;
cv::bitwise_not(gradient, gradient_padding);

cv::distanceTransform(gradient, gradient, CV_DIST_L2, CV_DIST_MASK_PRECISE);
cv::normalize(gradient, gradient, 0, 255, cv::NORM_MINMAX, CV_8U);

cv::bitwise_or(gradient, gradient_padding, gradient);

cv::imshow("gradient-distxform.png", gradient);
cv::waitKey();

}

Gradient from distance transform

关于c++ - 用渐变填充圆圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46466563/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com