一、话说直线拟合

霍夫直线检测容易受到线段形状与噪声的干扰而失真,这个时候我们需要另辟蹊径,通过对图像进行二值分析,提取骨架,对骨架像素点拟合生成直线,这种做法在一些场景下非常有效,而且效果还比较好。前面已经讲过霍夫变换,这里就不再叙述,直接上干货。

二、距离变换

距离变换是二值图像处理与操作中常用手段,在骨架提取,图像窄化中常有应用。距离变换的结果是得到一张与输入图像类似的灰度图像,但是灰度值只出现在前景区域。并且越远离背景边缘的像素灰度值越大。OpenCV中距离变换的函数如下:

void distanceTransform( InputArray src, OutputArray dst, int distanceType, int maskSize, int dstType=CV_32F);@param src 8-bit, single-channel (binary) source image.

@param dst Output image with calculated distances. It is a 8-bit or 32-bit floating-point,single-channel image of the same size as src .

@param distanceType Type of distance, see cv::DistanceTypes

@param maskSize Size of the distance transform mask, see cv::DistanceTransformMasks. In case of the DIST_L1 or DIST_C distance type, the parameter is forced to 3 because a \f$3\times 3\f$ mask gives
the same result as \f$5\times 5\f$ or any larger aperture.
@param dstType Type of output image. It can be CV_8U or CV_32F. Type CV_8U can be used only for the first variant of the function and distanceType == DIST_L1.

DIST_L1、DIST_L2、DIST_C计算像素距离方式如下:

其中当选择DIST_L2与DIST_MASK_PRECISE时候,OpenCV会使用TBB并行计算加速,DIST_L1与DIST_C是比较精确的距离计算方式、DIST_L2是比较快而粗糙的距离计算方式。下图是基于DIST_L2计算得到结果:

三、水平与垂直投影

关于这个OpenCV中我没有发现直接可以使用的相关API,所以我自己写了点代码,二值图像的水平或者垂直投影可以用于粘连字符分割、对象分离,发现局部极大值像素等处理,是非常重要的二值图像分析与处理手段。假设有二值图像与其像素分布如下:

其水平与垂直投影则分别如下:

四、实验

以上讲了这么多,是时候展现真正的技术了。今天看的内容大部分来源于opencv学堂,里面已经展示了部分代码,这里我将完整代码拿出来。

c++版本是自己写的:

int main()
{Mat src = imread("D:\\cv_study\\Exercise\\line\\lines.jpg");Mat gray, binary, dist;Mat result = Mat::zeros(480,640, CV_8UC1);int w = src.cols;cvtColor(src, gray, CV_BGR2GRAY);threshold(gray, binary,0,255, THRESH_BINARY | THRESH_OTSU);distanceTransform(binary, dist, DIST_L1, DIST_MASK_PRECISE);dist = dist / 15;vector<Point>ypts;vector<Point>xpts;Vec4f lines;Vec4f ls;for (int row = 0; row < dist.rows; row++){int cx = 0;int cy = 0;float max_d = 0;for (int col = 0; col < dist.cols; col++){float d = dist.at<float>(row, col);if (d > max_d){max_d = d;cx = col;cy = row;}}result.at<uchar>(cy, cx) = 255;Point p(cx, cy);ypts.push_back(p);}for (int col = 0; col < gray.cols; col++){int cx = 0;int cy = 0;float max_d = 0;for (int row = 0; row < gray.rows; row++){float d = dist.at<float>(row, col);if (d > max_d){max_d = d;cx = col;cy = row;}}result.at<uchar>(cy, cx) = 255;Point p1(cx, cy);xpts.push_back(p1);}fitLine(ypts, lines, DIST_L1, 0, 0.01, 0.01);fitLine(xpts, ls, DIST_L1, 0, 0.01, 0.01);float vx = lines[0];float vy = lines[1];float x = lines[2];float y = lines[3];int y1 = int((-x*vy / vx) + y);int y2 = int((w - x)*vy / vx + y);float vxs = ls[0];float vys = ls[1];float xs = ls[2];float ys = ls[3];int y1s = int((-xs*vys / vxs) + ys);int y2s = int((w - xs)*vys / vxs + ys);line(src, Point((w - 1), y2), Point(0, y1), Scalar(255, 0, 0), 2);line(src, Point((w - 1), y2s), Point(0, y1s), Scalar(0, 0, 255), 2);waitKey();return 0;
}

整体思想就是,将图像转换为灰度图,二值化,距离变换,骨架提取,根据骨架拟合直线。

python版本:

import numpy as np
import cv2class linedetector:def __init__(self):self.lines = []def find_lines(self, frame):h, w, ch = frame.shapegray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)cv2.imshow("binary image", binary)cv2.imwrite("D:/Python/opencv/binary.png", binary)dist = cv2.distanceTransform(binary, cv2.DIST_L1, cv2.DIST_MASK_PRECISE)cv2.imshow("distance", dist / 15)dist = dist / 15result = np.zeros((h, w), dtype=np.uint8)ypts = []for row in range(h):cx = 0cy = 0max_d = 0for col in range(w):d = dist[row][col]if d > max_d:max_d = dcx = colcy = rowresult[cy][cx] = 255ypts.append([cx, cy])xpts = []for col in range(w):cx = 0cy = 0max_d = 0for row in range(h):d = dist[row][col]if d > max_d:max_d = dcx = colcy = rowresult[cy][cx] = 255xpts.append([cx, cy])cv2.imshow("lines", result)cv2.imwrite("D:/Python/opencv/skeleton.png", result)frame = self.line_fitness(ypts, image=frame)frame = self.line_fitness(xpts, image=frame, color=(255, 0, 0))cv2.imshow("fit-lines", frame)cv2.imwrite("D:/Python/opencv/fitlines.png", frame)return self.linesdef line_fitness(self, pts, image, color=(0, 0, 255)):h, w, ch = image.shape[vx, vy, x, y] = cv2.fitLine(np.array(pts), cv2.DIST_L1, 0, 0.01, 0.01)y1 = int((-x * vy / vx) + y)y2 = int(((w - x) * vy / vx) + y)cv2.line(image, (w - 1, y2), (0, y1), color, 2)return imageif __name__ == "__main__":src = cv2.imread('D:/Python/opencv/lines.jpg')ld = linedetector()lines = ld.find_lines(src)cv2.waitKey(0)cv2.destroyAllWindows()

小编能力有限,不足之处多多谅解,今天就到这里

参考链接:点击打开链接

opencv 直线拟合相关推荐

  1. OpenCV直线拟合检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:opencv学堂 OpenCV直线拟合检测 霍夫直线检测 ...

  2. OpenCV 直线拟合及应用

    直线拟合顾名思义就是根据多个有限个数的点确定一条直线.依据为: 其中为第i个点到直线的距离,p(d)则为确定最小值的函数.而不同的p(d)对应着不同的直线拟合方法: OpenCV提供了7种(-1为用户 ...

  3. [OpenCV]直线拟合

    OpenCV实现了直线的拟合. CV_IMPL void cvFitLine( const CvArr* array, int dist, double param,double reps, doub ...

  4. OpenCV | 直线拟合fitline函数(Python)

    简介 之前做直线拟合时,自己写了一个利用最小二乘做直线拟合的程序,但是由于直线检测的误差比较大,拟合的效果并不好.个人不知道是什么原因,因此想尝试更改一下直线拟合的算法,后来找到了OpenCV中的fi ...

  5. OpenCV—直线拟合fitLine

    本文的主要参考为官方文档OpenCV249-fitLine和博客-OpenCV 学习(直线拟合) 以及<Learning OpenCV 3>page425-426 OpenCV中提供的直线 ...

  6. OpenCV——直线拟合

    相比于直线检测,直线拟合的最大特点是将所有数据只拟合出一条直线 void fitLine( InputArray points, OutputArray line, int distType,doub ...

  7. OpenCV | 直线拟合fitline函数

    学习目标: 学习掌握OpenCV的fitline函数 学习内容: cv::fitLine()的具体调用形式如下: void cv::fitLine( cv::InputArray points, // ...

  8. opencv直线拟合cv::fitLine()

    通过2D或者2D点集拟合直线 void fitLine( InputArray points, OutputArray line, int distType,double param, double ...

  9. OpenCV fitline直线拟合函数学习

    下图是OpenCV官方文档中,对直线拟合函数的详细介绍: fitLine()函数用于,对二维或三维空间中的点集进行直线拟合.共有六个参数: param 1:输入的点集,可以是Mat或者vector&l ...

最新文章

  1. python学哪个版本-Python学习,要选哪个版本?
  2. 管理11gRAC基本命令 (转载) 很详细
  3. 一文带你看懂分布式软总线在家庭场景的应用
  4. PHP 入门 - 2.函数
  5. 公司管理项目管理中的技巧
  6. 突击计划——求整数中的较大者
  7. SQL注入学习part03:(结合sqli-libs学习:21-30关)
  8. java中float double利用BigDecimal运算
  9. c语言数组中找出相同的数,找出数组中重复的数字(c语言)
  10. 以太坊中的事件机制Feed
  11. Unity官方文档解读之如何使用粒子系统创建汽车尾气
  12. 网络安全风险评估原理
  13. enable 华为交换机ntdp_华为交换机常用命令
  14. 科学防疫宣传实践总结报告
  15. 操作系统面试题(史上最全、持续更新)
  16. image jpeg
  17. YY一下微信线下支付的场景
  18. 计算机网络 四、五层协议体系结构-----数据链路层
  19. php 根据银行卡号获取所属银行
  20. IE 阻止过期的 ActiveX 控件

热门文章

  1. 价值1000元的Python原创文档,涉及“Python基础“、“Python自动化“等,免费分享!
  2. [iOS基础控件 - 5.3] 电台APP可滚动主界面(UIScrollView制作)
  3. 免费视频在线教育网站Khan Academy正式发布iPad应用
  4. (转)yum服务器设置 — how to set up a yum repertory server
  5. 降维方法小结和理解:PCA、LDA、MDS、ISOMAP、SNE、T-SNE、AutoEncoder
  6. 送给女朋友的心形照片墙
  7. CIO:知道谁会购买iPhone 7吗?
  8. 后疫情时代还有必要进行线上教学的必要吗?
  9. 菲菲更名宝贝 得意非凡版 v1.9 免费绿色版
  10. [天涯原创大赛]这才是战争(初稿)--中国唯一一部通俗易懂并教会你解读战争的文字