直线的扫描转换算法
2018-01-31 19:37
190 查看
这是第一篇博客,顺便深入学习一下markdown语法。
之后的图形学文章都使用C++实现。
数值微分法
算法理论
算法实现
中点画线法
算法理论
算法实现
Bresenham画线算法
算法理论
算法实现
k=Δy/Δxk
4000
=Δy/Δx接着推导增量方式计算y坐标:
yi+1=kxi+1+B=k(xi+Δx)+B=kxi+kΔx+B=yi+kΔx(1)(1)yi+1=kxi+1+B=k(xi+Δx)+B=kxi+kΔx+B=yi+kΔx由于Δx=1Δx=1,所以每次yy递增kk。
这里注意opencv中at(i0,i1)函数是操作第i0行第i1列,所以需要把xy反过来。
总体还是比较简单。cv配置、函数搞的比较麻烦。opencv还需多多熟练。
根据(x0,y0)(x1,y1)(x0,y0)(x1,y1)两点坐标可以得到直线方程:
F(x,y)=ax+by+cF(x,y)=ax+by+c其中,a=y0−y1,b=x1−x0,c=x0y1−x1y0a=y0−y1,b=x1−x0,c=x0y1−x1y0
当F(x,y)>0F(x,y)>0时,点在直线上方。当确定P点位置后,下一个像素点处的中点M的判别式为:F(M)=F(x+1,y+0.5)=F(x,y)+a+0.5bF(M)=F(x+1,y+0.5)=F(x,y)+a+0.5b此时判断符号。若M点在直线上方,则选M下方的像素点。那么下一个需要判断的中点的判别式为:
F(xp+2,yp+0.5)=F(M)+aF(xp+2,yp+0.5)=F(M)+a如果M点在直线下方,则选上方的像素点,下一个中点的判别式为
F(xp+2,yp+1.5)=F(M)+a+bF(xp+2,yp+1.5)=F(M)+a+b而F(M)的初始值:
F(M0)=F(x0,y0)+a+0.5b=a+0.5bF(M0)=F(x0,y0)+a+0.5b=a+0.5b
由于把d的判别全部乘2了,可以避免小数的运算。斜率在其他范围内只要换换前后两点的顺序、换换x,y,就可以解决。
假设x列的像素已确定,那么下一个像素列坐标为x+1,行下标为y或y+1,具体是哪个取决于误差项d大于0.5还是小于0.5。每次x增加1,则误差随之增加k。程序中设e=d-0.5,则可判断e的正负值。当d>1d>1时,则只需执行d=d−1d=d−1。
以上。
之后的图形学文章都使用C++实现。
目录
目录数值微分法
算法理论
算法实现
中点画线法
算法理论
算法实现
Bresenham画线算法
算法理论
算法实现
数值微分法
数值微分法通过计算直线的斜率,计算每个x对应的y坐标,并取像素x,round(y)。本方法直观可行,但执行效率低。由于每步都需要进行浮点乘法运算与舍入运算,故需要增量的方法。算法理论
首先计算直线的斜率:k=Δy/Δxk
4000
=Δy/Δx接着推导增量方式计算y坐标:
yi+1=kxi+1+B=k(xi+Δx)+B=kxi+kΔx+B=yi+kΔx(1)(1)yi+1=kxi+1+B=k(xi+Δx)+B=kxi+kΔx+B=yi+kΔx由于Δx=1Δx=1,所以每次yy递增kk。
算法实现
利用openCV+Cpp进行实现。考虑了|k|∈[0,1]与|k|∉[0,1]|k|∈[0,1]与|k|∉[0,1]两种情形#include<iostream> #include<cmath> #include<opencv2/core/core.hpp> #include<opencv2/highgui/highgui.hpp> using namespace cv; void DDAline(Mat& m,const int x0, const int y0, const int x1, const int y1,const cv::Vec3b& v); int main(){ Mat imageROI = Mat(500, 1000, CV_8UC3, Scalar(255, 255, 255)); DDAline(imageROI, 0, 0,400, 200, Vec3b(0, 0, 0)); namedWindow("显示结果"); imshow("显示结果", imageROI); waitKey(); } void DDAline(Mat& m, const int x0, const int y0, const int x1, const int y1, const cv::Vec3b& v){ double k = double(y1 - y0) / (x1 - x0); if (k >= -1 && k <= 1){ double y = y0; int x = x0; for (x = x0; x <= x1; x++){ m.at<Vec3b>(int(y + 0.5),x ) = v; y += k; } } else{ double x = x0; int y = y0; k = 1 / k; for (y = y0; y <= y1; y++){ m.at<Vec3b>(y,int(x+0.5)) = v; x += k; } } }
这里注意opencv中at(i0,i1)函数是操作第i0行第i1列,所以需要把xy反过来。
总体还是比较简单。cv配置、函数搞的比较麻烦。opencv还需多多熟练。
中点画线法
算法理论
首先假定k∈[0,1]k∈[0,1]之间。根据(x0,y0)(x1,y1)(x0,y0)(x1,y1)两点坐标可以得到直线方程:
F(x,y)=ax+by+cF(x,y)=ax+by+c其中,a=y0−y1,b=x1−x0,c=x0y1−x1y0a=y0−y1,b=x1−x0,c=x0y1−x1y0
当F(x,y)>0F(x,y)>0时,点在直线上方。当确定P点位置后,下一个像素点处的中点M的判别式为:F(M)=F(x+1,y+0.5)=F(x,y)+a+0.5bF(M)=F(x+1,y+0.5)=F(x,y)+a+0.5b此时判断符号。若M点在直线上方,则选M下方的像素点。那么下一个需要判断的中点的判别式为:
F(xp+2,yp+0.5)=F(M)+aF(xp+2,yp+0.5)=F(M)+a如果M点在直线下方,则选上方的像素点,下一个中点的判别式为
F(xp+2,yp+1.5)=F(M)+a+bF(xp+2,yp+1.5)=F(M)+a+b而F(M)的初始值:
F(M0)=F(x0,y0)+a+0.5b=a+0.5bF(M0)=F(x0,y0)+a+0.5b=a+0.5b
算法实现
void MidpointLine(Mat& m, const int x0, const int y0, const int x1, const int y1, const cv::Vec3b& v){ int a = y0 - y1; int b = x1 - x0; int d0 = 2*a + b; int delta1 = 2*a; int delta2 = 2*(a + b); int x, y, d; for (x = x0, y = y0, d = d0; x <= x1; x++){ if (d < 0){ y++; d += delta2; } else{ d += delta1; } m.at<Vec3b>(y, x) = v; } }
由于把d的判别全部乘2了,可以避免小数的运算。斜率在其他范围内只要换换前后两点的顺序、换换x,y,就可以解决。
Bresenham画线算法
算法理论
还是首先假定k∈[0,1]k∈[0,1]。假设x列的像素已确定,那么下一个像素列坐标为x+1,行下标为y或y+1,具体是哪个取决于误差项d大于0.5还是小于0.5。每次x增加1,则误差随之增加k。程序中设e=d-0.5,则可判断e的正负值。当d>1d>1时,则只需执行d=d−1d=d−1。
算法实现
void BresenhamLine(Mat& m, const int x0, const int y0, const int x1, const int y1, const Vec3b& v){ int x, y, dx, dy; float k, e; dx = x1 - x0; dy = y1 - y0; k = double(dy) / dx; e = -0.5; for (x = x0, y = y0; x <= x1; x++){ m.at<Vec3b>(y, x) = v; e += k; if (e >= 0){ y++; e--; } } }
以上。
相关文章推荐
- 计算机图形学——直线的三种扫描转换算法
- 直线扫描转换(DDA画线算法)
- 直线扫描转换算法-中点画线法
- 计算机图形学 学习笔记(一):概述,直线扫描转换算法:DDA,中点画线算法,Bresenham算法
- 计算机图形学基础 : 基本图形生成算法之直线的扫描转换
- 直线的扫描转换-中点线算法推导
- Bresenham直线扫描算法
- 直线扫描算法
- OpenGL实现多边形扫描转换的扫描线算法
- 【图形学】直线扫描算法之---bresenham改进算法(任何斜率,任何方向)
- 计算机图形学之光栅图形学——多边形的扫描转换算法简介
- 多边形的扫描转换与区域填充算法
- [计算机图形学] 基于C#窗口的Bresenham直线扫描算法、种子填充法、扫描线填充法模拟软件设计(一)
- 光栅图形学——直线段的扫描转换算法
- [计算机图形学] 基于C#窗口的Bresenham直线扫描算法、种子填充法、扫描线填充法模拟软件设计(二)
- 光栅图形学——直线段的扫描转换算法
- 改进的有效边表算法,多边形的扫描转换
- 改进的有效边表算法,多边形的扫描转换
- 直线的扫描转换
- 计算机图形学基础 : 基本图形生成算法之圆的扫描转换