opencv笔记2
图像灰度
彩色图像转化为灰度图像的过程是图像的灰度化处理。彩色图像中的每个像素的颜色由R,G,B三个分量决定,而每个分量中可取值0-255,这样一个像素点可以有256*256*256变化。而灰度图像是R,G,B三个分量相同的一种特殊的彩色图像,其中一个像素点的变化范围为256种。灰度图像的描述与彩色图像一样仍然反映了整副图像的整体和局部的色度和高亮等级的分布和特征。
在OpenCV中,用cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)来实现对图像进行灰度化处理。
import cv2
import rclpy
from rclpy.node import Node
import numpy as np
from ament_index_python.packages import get_package_share_directory #获取shares目录绝对路径
class OpenCVNode(Node):
def readImg(self,img_name: str):
default_image_path = get_package_share_directory('yahboom_esp32ai_car')+'/resource/'+img_name
self.get_logger().info(f'打开图片:{default_image_path}')
img = cv2.imread(default_image_path)
self.get_logger().info(f'image shape:{img.shape}')
#灰度
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow('src',img)
cv2.imshow('gray',gray)
cv2.waitKey(0)
def main():
rclpy.init()
node = OpenCVNode('opencvNode')
node.readImg('2.jpg')
rclpy.spin(node)
rclpy.shutdown()
效果
OpenCV图像二值化处理
给定阈值,大于阈值的为0(黑色)或 255(白色),使图像称为黑白图。阈值可固定,也可以自适应阈值。自适应阈值一般为一点像素与这点为中序的区域像素平均值或者高斯分布加权和的比较。
cv2.threshold(src, threshold, maxValue, thresholdType)
参数含义:
src:原图像
threshold:当前阈值
maxVal:最大阈值,一般为255
thresholdType:阈值类型
- cv.THRESH_BINARY
- cv.THRESH_BINARY_INV
- cv.THRESH_TRUNC
- cv.THRESH_TOZERO
- cv.THRESH_TOZERO_INV
返回值:
retval:与参数thresh一致
dst: 结果图像
import cv2
import rclpy
from rclpy.node import Node
import numpy as np
from ament_index_python.packages import get_package_share_directory #获取shares目录绝对路径
class OpenCVNode(Node):
def readImg(self,img_name: str):
default_image_path = get_package_share_directory('yahboom_esp32ai_car')+'/resource/'+img_name
self.get_logger().info(f'打开图片:{default_image_path}')
src = cv2.imread(default_image_path)
#灰度
img = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
ret,thresh1 = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
ret,thresh2 = cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV)
ret,thresh3 = cv2.threshold(img,127,255,cv2.THRESH_TRUNC)
ret,thresh4 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO)
ret,thresh5 = cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV)
cv2.imshow('gray',img)
cv2.imshow('BINARY',thresh1)
cv2.imshow('BINARY_INV',thresh2)
cv2.imshow('TRUNC',thresh3)
cv2.imshow('TOZERO',thresh4)
cv2.imshow('TOZERO_INV',thresh5)
cv2.waitKey(0)
def main():
rclpy.init()
node = OpenCVNode('opencvNode')
node.readImg('1.jpg')
rclpy.spin(node)
rclpy.shutdown()
效果如下
图像边缘检测
边缘检测是识别出图像中亮度变化剧烈的像素点构成的集合。图像边缘的正确检测对于分析图像中的内容、实现图像中物体的分割、定位等具有重要的作用。边缘检测大大减少了源图像的数据量,显著减少图像的数据规模。主要是从数学角度去分类,简单了解下背景:如果将图像的每一行像素和每一列像素都描述成一个关于灰度值的函数,函数值的变化趋势可以用函数的导数描述,图像的边缘对应在灰度值函数中是函数值突然变大的区域,进而确定图像中的边缘位置。
分类如下:
一阶导数的边缘检测算子:通过计算图像的梯度值来检测图像的边缘,常见的有Roberts算子、Sobel算子和Prewitt算子。
二阶导数的边缘算子:通过寻求二阶导数中的过零点来检测边缘,,常见的有Laplacian 算子,此类算子对噪声敏感。
其他边缘算子:前面两类均是通过微分算子来检测图像边缘,还有一种就是Canny算子,其是在满足一定约束条件下推导出来的边缘检测最优化算子。
目前有多种算法可以进行边缘检测,虽然Canny算法年代久远,但可以说它是边缘检测的一种标准算法,而且仍在研究中广泛使用。
Canny算子的简要步骤如下:
(1)去噪声:应用高斯滤波来平滑图像,目的是去除噪声
(2)梯度:找寻图像的梯度
(3)非极大值抑制:应用非最大抑制技术来过滤掉非边缘像素,将模糊的边界变得清晰。该过程保留了每个像素点上梯度强度的极大值,过滤掉其他的值。
(4)应用双阈值的方法来区分强边缘和弱边缘
(5)利用滞后技术来跟踪边界。若某一像素位置和强边界相连的弱边界认为是边界,其他的弱边界则被删除。
背后有很多数学推导过程,网上很多大佬写文章介绍,还有很多深度展开调整参数的。
https://blog.csdn.net/zaishuiyifangxym/article/details/90142702
https://zhuanlan.zhihu.com/p/447565904
https://zhuanlan.zhihu.com/p/99959996
看下OpenCV里面,canny算法的实现步骤
.Canny方法处理得到图像:edges=cv2.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
参数含义:
edges:计算得到的边缘图像
image :计算得到的边缘图像,一般是高斯处理后得到的图像
threshold1 :处理过程中的第一个阈值
threshold2 :处理过程中的第二个阈值
apertureSize :Sobel 算子的孔径大小
import cv2
import rclpy
from rclpy.node import Node
import numpy as np
from ament_index_python.packages import get_package_share_directory #获取shares目录绝对路径
class OpenCVNode(Node):
def readImg(self,img_name: str):
default_image_path = get_package_share_directory('yahboom_esp32ai_car')+'/resource/'+img_name
self.get_logger().info(f'打开图片:{default_image_path}')
img = cv2.imread(default_image_path)
#灰度
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#高斯降噪
gaussian = cv2.GaussianBlur(gray, (5, 5), 0)
# Canny算子
Canny50 = cv2.Canny(gaussian, 50, 50)
Canny100 = cv2.Canny(gaussian, 50, 100)
Canny150 = cv2.Canny(gaussian, 50, 150)
#
cv2.imshow('gray',gray)
cv2.imshow('Canny50',Canny50)
cv2.imshow('Canny100',Canny100)
cv2.imshow('Canny150',Canny150)
cv2.waitKey(0)
def main():
rclpy.init()
node = OpenCVNode('opencvNode')
node.readImg('e.jpg')
rclpy.spin(node)
rclpy.shutdown()
通过调整canny参数,可见效果不同,第二个阈值越大,图片丢失细节越多。
OpenCV绘制图形
划线
cv2.line(dst,pt1,pt2,color,thickness=None,lineType=None,shift=None)函数进行线段的绘制。
参数含义:
dst:输出图像。
pt1,pt2:必选参数。线段的坐标点,分别表示起始点和终止点
color:必选参数。用于设置线段的颜色
thickness:可选参数。用于设置线段的宽度
lineType:可选参数。用于设置线段的类型,可选8(8邻接连接线-默认)、4(4邻接连接线)和cv2.LINE_AA 为抗锯齿
画矩形
cv2.rectangle(img,pt1,pt2,color,thickness=None,lineType=None,shift=None)
参数含义:
img:画布或者载体图像
pt1,pt2:必选参数。矩形的顶点,分别表示顶点与对角顶点,即矩形的左上角与右下角(这两个顶点可以确定一个唯一的矩形),可以理解成是对角线。
color:必选参数。用于设置矩形的颜色
画圆
cv2.circle(img, center, radius, color[,thickness[,lineType]])
参数含义:
img:画或者载体图像布
center:为圆心坐标,格式: (50,50)
radius:半径
thickness: 线条粗细。默认为1.如果-1则为填充实心
lineType:线条类型。
画椭圆
cv2.ellipse(img, center, axes, angle, StartAngle, endAngle, color[,thickness[,lineType]
参数含义:
center:椭圆的中心点,(x,y)
axes:指的是短半径和长半径,(x,y)
StartAngle:圆弧起始角的角度
endAngle:圆弧终结角的角度
画多边形
cv2.polylines(img,[pts],isClosed, color[,thickness[,lineType]])
参数含义:
pts:多边形的顶点
isClosed:是否闭合。(True/False)
文字
cv2.putText(img, str, origin, font, size,color,thickness)
参数含义:
img:输入图像
str:绘制的文字
origin:左上角坐标(整数),可以理解成文字是从哪里开始的
font:字体
size:字体大小
color:字体颜色
thickness:字体粗细
import cv2
import rclpy
from rclpy.node import Node
import numpy as np
from ament_index_python.packages import get_package_share_directory #获取shares目录绝对路径
class OpenCVNode(Node):
def readImg(self,img_name: str):
default_image_path = get_package_share_directory('yahboom_esp32ai_car')+'/resource/'+img_name
self.get_logger().info(f'打开图片:{default_image_path}')
img = cv2.imread(default_image_path)
#划线
line = cv2.line(img, (50,20), (20,100), (255,0,255), 10)
#画矩形
rect = cv2.rectangle(img, (110,50), (200,200), (255,0,255), 10)
#画圆
circle = cv2.circle(img, (280,120), 50, (255,0,255), 10)
#画椭圆
ellipse = cv2.ellipse(img, (400,120), (20,50),0,0, 360,(255,0,255), 5)
# text
cv2.putText(img,'bohu text test',(50,550),cv2.FONT_HERSHEY_SIMPLEX,1,(0,200,0),2)
#多边形
points = np.array([[120,250], [340,440], [350,410], [250,250]], np.int32)
cv2.polylines(img, [points],True,(255,0,255), 5)
cv2.imshow('gray',img)
cv2.waitKey(0)
def main():
rclpy.init()
node = OpenCVNode('opencvNode')
node.readImg('e.jpg')
rclpy.spin(node)
rclpy.shutdown()