opencv 直线拟合

article/2025/11/8 4:51:30

一、话说直线拟合

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

二、距离变换

距离变换是二值图像处理与操作中常用手段,在骨架提取,图像窄化中常有应用。距离变换的结果是得到一张与输入图像类似的灰度图像,但是灰度值只出现在前景区域。并且越远离背景边缘的像素灰度值越大。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()



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

参考链接:点击打开链接


http://chatgpt.dhexx.cn/article/gnn4HTmA.shtml

相关文章

拟合算法之一 直线拟合

直线拟合 很早就想学习拟合了&#xff0c;经常听同事用到拟合&#xff0c;当时尚且一窍不通&#xff0c;必须快递加急紧追此处才是&#xff0c;也参考了网上大佬的一些宝贵经验&#xff0c;先将拟合方法总结如下&#xff1a; 最小二乘法 1.原理 2.举例实现 void fitline3(…

直线拟合问题(Python实现)

程序如下&#xff1a; import matplotlib.pyplot as plt import numpy as npx_list [466, 741, 950, 1422, 1634] y_list [7.04, 4.28, 3.40, 2.54, 2.13] # x_list [0, 1, 3, 5] # y_list [1, 2, 4, 8]l_mat11 len(x_list) l_mat12 l_mat21 sum(x for x in x_list) l_…

OpenCV直线拟合检测

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达本文转自&#xff1a;opencv学堂 OpenCV直线拟合检测 霍夫直线检测容易受到线段形状与噪声的干扰而失真&#xff0c;这个时候我们需要另辟蹊径&#xff0c;通过对图像进行…

RANSAC 直线拟合

result&#xff1a; code&#xff1a; #include "stdafx.h". #include <opencv2\opencv.hpp> #include <iostream> #include <ctime>using namespace std; using namespace cv;//生成[0,1]之间符合均匀分布的数 double uniformRandom(void) {ret…

OpenCV——直线拟合

相比于直线检测&#xff0c;直线拟合的最大特点是将所有数据只拟合出一条直线 void fitLine( InputArray points, OutputArray line, int distType,double param, double reps, double aeps ); points&#xff1a;输入待拟合直线的2D或者3D点集。line&#xff1a;输出描述直线…

直线拟合

在进行直线拟合算法中&#xff0c;一直使用最小二乘法&#xff0c;使用时间长了&#xff0c;也比较熟练了&#xff0c;但是在最近一次使用中&#xff0c;最小二乘法在拟合垂直或者接近垂直的直线时&#xff0c;效果不好&#xff1b;斜率很大&#xff0c;使用稳定性不好。查阅《…

Android 冷启动 热启动 测试

一、应用的启动 启动方式 通常来说&#xff0c;在安卓中应用的启动方式分为两种&#xff1a;冷启动和热启动。 1、冷启动&#xff1a;当启动应用时&#xff0c;后台没有该应用的进程&#xff0c;这时系统会重新创建一个新的进程分配给该应用&#xff0c;这个启动方式就是冷启动…

Spring Boot 热启动

目的&#xff1a;修改类文件可以马上编译发布&#xff0c;提高了工作效率 步骤&#xff1a; 第一步&#xff1a; 修改pom.xml <!-- 热启动 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools&l…

APP冷热启动专项测试

一、冷热启动的概念 冷启动&#xff1a;当启动应用时&#xff0c;后台没有该应用的进程&#xff0c;这时系统会重新创建一个新的进程分配给该应用&#xff0c;这个启动方式就是冷启动。 热启动&#xff1a;当启动应用时&#xff0c;后台已有该应用的进程&#xff08;例&#…

嵌入式linux热启动和冷启动,使用keil判断ARM的冷启动和热启动的方法

微处理器:LPC2114 编译环境:Keil MDK V4.10 思路: 常把单片机系统的复位分为冷启动和热启动。所谓冷启动&#xff0c;也就是一般所说的上电复位&#xff0c;冷启动后片内外RAM的内容是随机的&#xff0c;通常是0x00或0xFF&#xff1b;单片机的热启动是通过外部电路给运行中的单…

Android冷启动和热启动以及冷启动优化方案

1、什么是冷启动和热启动 冷启动&#xff1a; 当启动应用时&#xff0c;后台没有该应用的进程&#xff0c;这时系统会重新创建一个新的进程分配给该应用&#xff0c;这个启动方式就是冷启动&#xff0c;也就是先实例化Application。热启动&#xff1a; 当启动应用时&#xff0…

冷启动和热启动的区别android,app冷启动和热启动的区别(详解两者定义及区别)...

介绍一下 app 冷启动和热启动方式来实现 app 秒开的效果。那么,先来看看什么叫冷启动和热启动。 冷启动:指 app 被后台杀死后,在这个状态打开 app,这种启动方式叫做冷启动。 热启动:指 app 没有被后台杀死,仍然在后台运行,通常我们再次去打开这个 app,这种启动方式叫热…

热启动和冷启动以及复位启动的小知识

热启动和冷启动的区别&#xff1a; 1、重启是热启动。开机是冷启动。 2、热启动是通过开始菜单、任务管理器或者快捷键&#xff0c;重新启动计算机&#xff0c;叫热启动。冷启动是在关机状态下按POWER启动计算机&#xff0c;叫做冷启动 。 3、热启动是在计算机已经开启的状态…

dimen属性报错

<TextViewandroid:id"id/tvQuote1"android:layout_width"fill_parent"android:layout_height"wrap_content"android:textColor"#FFFFFF"android:textSize"dimen/text_size" /> 发现问题是dimen属性出现错误 别的手机上…

解决android:padding=“@dimen/activity_vertical_margin“> 标红问题

解决android:padding“dimen/activity_vertical_margin”> 标红问题 如果有这个问题&#xff0c;可以在values中新建一个dimen.xml文件 在dimen.xml里增加如下代码&#xff1a; <?xml version"1.0" encoding"utf-8"?><resources><…

android:paddingTop=“@dimen/activity_horizontal_margin“报错(报红)解决方法

android:paddingTop"dimen/activity_horizontal_margin"报错&#xff08;报红&#xff09;解决方法 在app----->res----->values------>dimens.xml中添加如下代码&#xff1a; <dimen name“activity_horizontal_margin” / (后面还有一个尖括号)&#…

android 手机适配之values适配dimen值

android 适配屏幕的方式有很多,最方便最直接的无非就是适配values里的dimens文件值来进行适配. 张鸿洋大神已经写过一篇适配的文章,很详细 但是我在阅读的时候还是有点疑问,这个values-1920x1080到底是dp值还是手机分辨率,因为我在实际操作中发现这样一句话. 很明显可以看…

Android开发——AS插件批量解决XML中的String/Color/Dimen硬编码

1. 问题抛出 1.1 开发方面 对于日常开发中&#xff0c;每写一个"#333"&#xff0c;都要手动的在当前xml与colors.xml中来回切换&#xff0c;查看是否已经定义过&#xff0c;如果定义过则拿过来复用&#xff0c;如果没有就要新定义一个叫"#333"的资源名&a…

dimen.xml浅析

转自&#xff1a;http://blog.csdn.net/kazeik/article/details/8268721 有时候我们为了维护一个工程&#xff0c;或者想定义一个button样式&#xff0c;或textView样式&#xff0c;这些样式中包含着文字的大小&#xff0c;背景图片&#xff0c;前置图片等一些资源。而且这个…

android:屏幕自适应之dimen使用

From&#xff1a;4种必须知道的Android屏幕自适应解决方案&#xff08;求投票支持&#xff09; demo下载&#xff1a;http://www.eoeandroid.com/forum.php?modattachment&aidNjE0Njh8ZTIyZDA2M2N8MTMzODgyOTQxN3w1NzAwOTV8MTczOTcz 以下是Demo首页的预览图 一、细说 layo…