栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

GAMES101作业4-贝塞尔曲线&OpenCV图像处理

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

GAMES101作业4-贝塞尔曲线&OpenCV图像处理

目录

作业内容

实现代码

分段解析

mouse_handler()函数

 cv处理鼠标事件

naive_bezier()

recursive_bezier()递归找出点轨迹

main()函数

cvtColor()

图像色彩模式

参考


作业内容

实现代码
#include 
#include 
#include 

std::vector control_points;//控制点-动态数组
void mouse_handler(int event, int x, int y, int flags, void *userdata) 
{
    if (event == cv::EVENT_LBUTTONDOWN && control_points.size() < 4) 
    {
        std::cout << "Left button of the mouse is clicked - position (" << x << ", "
        << y << ")" << 'n';
        control_points.emplace_back(x, y);
    }     
}

void naive_bezier(const std::vector &points, cv::Mat &window) 
{
    auto &p_0 = points[0];
    auto &p_1 = points[1];
    auto &p_2 = points[2];
    auto &p_3 = points[3];

    for (double t = 0.0; t <= 1.0; t += 0.001) 
    {
        auto point = std::pow(1 - t, 3) * p_0 + 3 * t * std::pow(1 - t, 2) * p_1 +
                 3 * std::pow(t, 2) * (1 - t) * p_2 + std::pow(t, 3) * p_3;

        window.at(point.y, point.x)[2] = 255;
    }
}

cv::Point2f recursive_bezier(const std::vector &control_points, float t) 
{
    int n = control_points.size();
    if (n == 1) return control_points[0];
    std::vector res_control_points;

    for (int i = 0; i  &control_points, cv::Mat &window) 
{
    // TODO: Iterate through all t = 0 to t = 1 with small steps, and call de Casteljau's 
    // recursive Bezier algorithm.
    for (double t = 0.0; t <= 1.0; t += 0.001)
    {
        cv::Point2f point = recursive_bezier(control_points, t);
        window.at(point.y, point.x)[1] = 255;
    }
}

int main() 
{
    cv::Mat window = cv::Mat(700, 700, CV_8UC3, cv::Scalar(0));
    cv::cvtColor(window, window, cv::COLOR_BGR2RGB);
    cv::namedWindow("Bezier Curve", cv::WINDOW_AUTOSIZE);

    cv::setMouseCallback("Bezier Curve", mouse_handler, nullptr);

    int key = -1;
    while (key != 27) 
    {
        for (auto &point : control_points) 
        {
            cv::circle(window, point, 3, {255, 255, 255}, 3);
        }

        if (control_points.size() == 4) 
        {
            naive_bezier(control_points, window);
            bezier(control_points, window);

            cv::imshow("Bezier Curve", window);
            cv::imwrite("my_bezier_curve.png", window);
            key = cv::waitKey(0);

            return 0;
        }

        cv::imshow("Bezier Curve", window);
        key = cv::waitKey(20);
    }

return 0;
}

分段解析

mouse_handler()函数
void mouse_handler(int event, int x, int y, int flags, void *userdata) 
{
    //event是鼠标事件:滑动,点击,双击等动作
    //x 鼠标点击点的横坐标
    //y 鼠标点击点的纵坐标
    //flags 鼠标拖拽以及键盘和鼠标联合事件:鼠标拖拽,按住ctrl不放等
    if (event == cv::EVENT_LBUTTONDOWN && control_points.size() < 4) 
    {
        std::cout << "Left button of the mouse is clicked - position (" << x << ", "
        << y << ")" << 'n';
        control_points.emplace_back(x, y);
    }     
}

可以观察在用鼠标操作时,窗口会根据这个回调函数输出命令:

 cv处理鼠标事件

setMouseCallback()函数是用来处理鼠标动作的函数,我们可以利用它来做有用的操作来处理鼠标动作,首先需要创建一个回调函数,当鼠标事件触发时,该函数执行。

Even包含:滑动,点击,放开,双击等;

详见参考:OpenCV处理鼠标事件方法_bubble_story的博客

naive_bezier()
void naive_bezier(const std::vector &points, cv::Mat &window) 
{
    auto &p_0 = points[0];
    auto &p_1 = points[1];
    auto &p_2 = points[2];
    auto &p_3 = points[3];

    for (double t = 0.0; t <= 1.0; t += 0.001) 
    {
        auto point = std::pow(1 - t, 3) * p_0 + 3 * t * std::pow(1 - t, 2) * p_1 +
                 3 * std::pow(t, 2) * (1 - t) * p_2 + std::pow(t, 3) * p_3;
        //img.at(int y, int x)代表(x, y)坐标的颜色明度
       //img.at(int y, int x)[] 012分别对应RGB值
        window.at(point.y, point.x)[2] = 255;
    }
}

recursive_bezier()递归找出点轨迹
cv::Point2f recursive_bezier(const std::vector &control_points, float t) 
{
    // TODO: Implement de Casteljau's algorithm
    //recrusive - 递归 这里是一个递归贝塞尔,要用到循环
    
    //在实现递归前需要确定两个变量:1.控制点的数量n 2.t的值
    int n = control_points.size();
    //如果n==1,则返回该点并终止
    if (n == 1) return control_points[0];
    //需要有个储存n-1控制点的动态数组vector,形式参考 std::vector &control_points
    std::vector res_control_points;
    //开始递归
    for (int i = 0; i  

关于贝塞尔曲线可以参考文章,讲的很好: 从零开始学图形学:10分钟看懂贝塞尔曲线 - 知乎 (zhihu.com)

main()函数
...
int main() 
{
    
    cv::Mat window = cv::Mat(700, 700, CV_8UC3, cv::Scalar(150,0,0));
    
    cv::cvtColor(window, window, cv::COLOR_BGR2RGB);
    cv::namedWindow("Bezier Curve", cv::WINDOW_AUTOSIZE);

    cv::setMouseCallback("Bezier Curve", mouse_handler, nullptr);

    int key = -1;
    while (key != 27) 
    {
        for (auto &point : control_points) 
        {
            
            cv::circle(window, point, 3, {255, 255, 255}, 3);
        }
...

cvtColor()

调用形式:

	void cv::cvtColor(
		cv::InputArray src, // 输入序列
		cv::OutputArray dst, // 输出序列
		int code, // 颜色映射码
		int dstCn = 0 // 输出的通道数 (0='automatic')
	);

支持多种颜色空间的转换,具体参考:【OpenCV3】颜色空间转换——cv::cvtColor()详解_PHILOS_THU的博客

图像色彩模式

(1)位图模式

最基本的格式,图象只有黑白,0或1,色彩图想转变成黑白图,要首先将图像转换成灰度模式再进行转换。

(2)灰度模式

使用256级的灰度来表示图像,一个像素相当于占用8为一个字节,每个像素值使用0到255的亮度值代表,其中0为黑色,255为白色,相当于从黑->灰->白的过渡。

(3)RGB模式

RGB模式的图像有3个颜色通道,分布为红(Red),绿(Green)和蓝(Bule),每个都占用8位一个字节来表示颜色信息,这样每个颜色的取值范围为0~255,那么就三种颜色就可以有多种组合。三个值相等 - 灰色;三个值都为0 - 黑色;三个值都为255 - 白色。

(4)HSB模式

根据日常生活中人眼的视觉对色彩的观察得而制定的一套色彩模式,最接近与人类对色彩的辨认的思考方式,所有的颜色都是用色彩三属性来描述

H:(色相):是指从物体反射或透过物体传播的颜色

S:(饱和度):是指颜色的强度或纯度,表示色相中灰色成分所占的比例

B:(亮度):是指颜色对相对明暗程度,通常 100%定义为白色;0%为黑色

参考

图像处理:c++ opensv数字图像处理3:通过鼠标点击操作获取图像的像素坐标和像素值_‭刘燚的博客

色彩模式:

学习opencv之cvtColor_Huo的藏经阁的博客-CSDN博客

鼠标事件:

OpenCV处理鼠标事件方法_bubble_story的博客

贝塞尔曲线:

从零开始学图形学:10分钟看懂贝塞尔曲线 - 知乎 (zhihu.com)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/923975.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号