对于使用OpenCVPython提取所有边界框感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍pythonopencv边缘提取,并为您提供关于c–OpenCV边界框、opencv-python-
对于使用OpenCV Python提取所有边界框感兴趣的读者,本文将会是一篇不错的选择,我们将详细介绍python opencv边缘提取,并为您提供关于c – OpenCV边界框、opencv-python-学习笔记二(利用opencv绘图)、OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像2、OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像一的有用信息。
本文目录一览:- 使用OpenCV Python提取所有边界框(python opencv边缘提取)
- c – OpenCV边界框
- opencv-python-学习笔记二(利用opencv绘图)
- OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像2
- OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像一
使用OpenCV Python提取所有边界框(python opencv边缘提取)
我有一幅包含多个边界框的图像。
我需要提取其中包含边界框的所有内容。到目前为止,从这个站点我已经得到了这个答案:
y = img[by:by+bh, bx:bx+bw]cv2.imwrite(string + ''.png'', y)
它有效,但是只有一个。我应该如何修改代码?我尝试将其放在轮廓循环中,但它仍会喷出一个图像而不是多个图像。
提前非常感谢您。
答案1
小编典典你去那里:
import cv2im = cv2.imread(''c:/data/ph.jpg'')gray=cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)contours, hierarchy = cv2.findContours(gray,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)[-2:]idx =0 for cnt in contours: idx += 1 x,y,w,h = cv2.boundingRect(cnt) roi=im[y:y+h,x:x+w] cv2.imwrite(str(idx) + ''.jpg'', roi) #cv2.rectangle(im,(x,y),(x+w,y+h),(200,0,0),2)cv2.imshow(''img'',im)cv2.waitKey(0)
c – OpenCV边界框
我遇到的问题是边界框被淹没不止一次,实际上绘制了多个框.我过去几天试图做的是以某种方式消除绘制的盒子数量并且只绘制一个大的边界框.
我正在寻找一些技术来填充整个对象,我相信在这种情况下会有所帮助.
下面我发布了用于实现图像中显示的结果的代码:
vector<vector<Point> > contours; vector<Vec4i> hierarchy; vector<Vec3f> vecCircles; vector<Vec3f>::iterator itrCircles; while(1) { Mat frame; cap >> frame; // get a new frame from camera ///////////////////// Mat imgHSV; cvtColor( frame,imgHSV,CV_BGR2HSV ); //////////////////// Mat blur_out; GaussianBlur(imgHSV,blur_out,Size(1,1),2.0,2.0); //////////////////// Mat range_out; inRange(blur_out,Scalar(100,100,100),Scalar(120,255,255),range_out); //////////////////// findContours(range_out,contours,hierarchy,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0) ); /// Approximate contours to polygons + get bounding rects and circles vector<vector<Point> > contours_poly( contours.size() ); vector<Rect> boundRect( contours.size() ); vector<Point2f>center( contours.size() ); vector<float>radius( contours.size() ); for( int i = 0; i < contours.size(); i++ ) { approxpolyDP( Mat(contours[i]),contours_poly[i],3,true ); boundRect[i] = boundingRect( Mat(contours_poly[i]) ); } /// Draw polygonal contour + bonding rects Mat drawing = Mat::zeros( range_out.size(),CV_8UC3 ); for( int i = 0; i< contours.size(); i++ ) { Scalar color = Scalar(255,255); drawContours( drawing,contours_poly,i,color,1,8,vector<Vec4i>(),Point() ); rectangle( drawing,boundRect[i].tl(),boundRect[i].br(),2,0 ); }
如果有人可以提出一些提示或提供一些信息来源,我可以找到我的问题的答案.
编辑(快速更新):
我设法将输出图像逐渐安静地提升到安静的结果.关键是使用erode& amp;扩张以及我的findContours()函数.我将CV_RETR_TREE更改为CV_RETR_EXTERNAL.我还解决了一些其他小事,但效果很好:
不知道我是否应该在这里写这个或打开新的线程….但现在我需要一些帮助组件标签和提取参数,如中心点和区域.
总结
以上是小编为你收集整理的c – OpenCV边界框全部内容。
如果觉得小编网站内容还不错,欢迎将小编网站推荐给好友。
opencv-python-学习笔记二(利用opencv绘图)
常见参数:
color:颜色(255,255,0),BGR表示
thickness:线宽px,-1代表填充
linetype:圆边界类型。cv.LINE_4,cv.LINE_8,cv.LINE_AA,AA代表抗锯齿线
shift:图形缩小倍数
线
常见函数:
cv.arrowedLine() 箭头线
cv.arrowedLine(img, pt1, pt2, color[, thickness[, line_type[, shift[, tipLength]]]])
pt1:箭头起点(x,y)
pt2:箭头终点(x,y)
tipLength:
import numpy as np
import cv2 as cv
# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
cv.arrowedLine(img, (0, 0), (255, 255), (255, 255, 255))
# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMAL
cv.namedWindow(''circle'', cv.WINDOW_NORMAL)
# 显示图像
cv.imshow(''circle'', img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.line() 直线
cv.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
pt1:起点(x,y)
pt2:终点(x,y)
import numpy as np
import cv2 as cv
# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
cv.line(img, (255, 255), (274, 274), (240, 240, 240), 10)
# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMAL
cv.namedWindow(''circle'', cv.WINDOW_NORMAL)
# 显示图像
cv.imshow(''circle'', img)
cv.waitKey(0)
cv.destroyAllWindows()
圆
常见函数:
cv.circle() 圆
cv.circle(img, center, radius, color[, thickness[, lineType[, shift]]])
img:
center:圆心(x,y)
radius:半径 int
import numpy as np
import cv2 as cv
# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
cv.circle(img, (447, 63), 63, (255, 255, 255), -1)
# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMAL
cv.namedWindow(''circle'', cv.WINDOW_NORMAL)
# 显示图像
cv.imshow(''circle'', img)
cv.waitKey(0)
cv.destroyAllWindows()
矩形
常见函数
cv.rectangle
cv.rectangle(img, pt1, pt2, color[, thickness[, lineType[, shift]]])
pt1:对角,左上点
pt2:对角,右下点
import numpy as np
import cv2 as cv
# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
cv.rectangle(img, ((10, 10), (40, 40)), (255, 255, 255))
# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMAL
cv.namedWindow(''circle'')
# 显示图像
cv.imshow(''circle'', img)
cv.waitKey(0)
cv.destroyAllWindows()
其它
常见函数
cv.drawMarker() 在指定点出标记
cv.drawMarker(img, position, color[, markerType[, markerSize[, thickness[, line_type]]]])
position:点位置 (x,y)
markerType:标记类型
import numpy as np
import cv2 as cv
# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
cv.drawMarker(img, (260, 260), (255, 255, 255)
# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMAL
cv.namedWindow(''circle'')
# 显示图像
cv.imshow(''circle'', img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.putText() 绘制文本字符串
cv.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]])
org:位置
text:字符串内容
fontFace:
cv.FONT_HERSHEY_SIMPLEX
|
normal size sans-serif font |
cv.FONT_HERSHEY_PLAIN
|
small size sans-serif font |
cv.FONT_HERSHEY_DUPLEX
|
normal size sans-serif font (more complex than FONT_HERSHEY_SIMPLEX) |
cv.FONT_HERSHEY_COMPLEX
|
normal size serif font |
cv.FONT_HERSHEY_TRIPLEX
|
normal size serif font (more complex than FONT_HERSHEY_COMPLEX) |
cv.FONT_HERSHEY_COMPLEX_SMALL
|
smaller version of FONT_HERSHEY_COMPLEX |
cv.FONT_HERSHEY_SCRIPT_SIMPLEX
|
hand-writing style font |
cv.FONT_HERSHEY_SCRIPT_COMPLEX
|
more complex variant of FONT_HERSHEY_SCRIPT_SIMPLEX |
cv.FONT_ITALIC
|
flag for italic font |
fontScale:字体缩放倍数
bottomLeftOrigin:true:。false:反转。
import numpy as np
import cv2 as cv
# Create a black image
img = np.zeros((512, 512, 3), np.uint8)
# cv.circle(img, (447, 63), 63, (255, 255, 255), -1)
# cv.arrowedLine(img, (0, 0), (255, 255), (255, 255, 255))
# cv.drawMarker(img, (260, 260), (255, 255, 255) )
# cv.line(img, (255, 255), (274, 274), (240, 240, 240), 10)
cv.putText( img, "opencv", (200, 200), cv.FONT_HERSHEY_PLAIN, 1, (255, 255, 255))
# cv.WINDOW_AUTOSIZE cv.WINDOW_NORMAL
cv.namedWindow(''circle'')
# 显示图像
cv.imshow(''circle'', img)
cv.waitKey(0)
cv.destroyAllWindows()
OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像2
3.5、Canny边缘检测
OpenCV提供了Canny边缘检测函数来识别边缘。它有5个步骤:使用高斯滤波器对图像进行去噪、计算梯度、在边缘上使用最大抑制(NMS)、在检测到的边缘上使用双阀值去除
假阳性(false positive),最后还会分析出所有的边缘及其之间的连接,以保留真正的边缘并消除不明显的边缘。
import cv2
import numpy as np
img = cv2.imread("flower.jpg")
cv2.imwrite("canny.jpg", cv2.Canny(img, 200, 300))
cv2.imshow("image", img)
cv2.imshow("canny", cv2.imread("canny.jpg"))
cv2.waitKey()
cv2.destroyAllWindows()
运行效果:
3.6、轮廓检测
在计算机视觉中,轮廓检测是另一个比较重要的任务,不单是用来检测图像或视频中物体的轮廓,而且还有其他操作与轮廓检测有关。这些操作有:计算多边形边界、
形状逼近和计算感兴趣区域。这是与图像数据交互时的简单操作,因为NumPy中的矩形区域可以使用数组切片(slice)来定义。在介绍物体检测(包括人脸)和物体跟踪的概念时会大量使用这种技术。
import cv2
import numpy as np
import os
img = np.zeros((200, 200), dtype = np.uint8) # 创建一个200x200大小的黑色空白图像,
img[50:150, 50:150] = 255 # 在图像的中央放置一个白色方块
ret, thresh = cv2.threshold(img, 127, 255, 0) #对图像进行二值化操作
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 寻找轮廓
color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR) # 颜色空间转换
img = cv2.drawContours(color, contours, -1, (0, 0, 255), 5) # 画出轮廓,-1,表示所有轮廓,画笔颜色为(0, 255, 255),即Red,粗细为5
cv2.imshow("contours",color)
cv2.waitKey()
cv2.destroyAllWindows()
findContours()函数有三个参数:输入图像、层次类型和轮廓逼近方法。
这个函数会修改输入图像,因此建议使用原始图像的一份拷贝(如:通过img.copy()来作为输入图像)。
由函数返回的层次树相当重要:cv2.RETR_TREE参数会得到图像中轮廓的整体层次结构,以此来建立轮廓之间的“关系”。如果只想得到最外面的轮廓,可使用cv2.RETR_EXTERNAL。
这对消除包含在其他轮廓中的轮廓很有用(如在大多数情形下,不需要检测一个目标包含在另一个与之相同的目标里面)
findContours()函数有三个返回值:修改后的图像、图像的轮廓以及它们的层次。使用轮廓来画出图像的彩色版本(即把轮廓画成绿色),并显示出来。
注意:返回三个值报错,实际上只返回两个值(图像的轮廓以及它们的层次)
cv2.threshold()简单阈值
这个函数有四个参数,第一个原图像,第二个进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的有:
cv2.THRESH_BINARY(黑白二值)
cv2.THRESH_BINARY_INV(黑白二值反转)
cv2.THRESH_TRUNC (得到的图像为多像素值)
cv2.THRESH_TOZERO
cv2.THRESH_TOZERO_INV
该函数有两个返回值,第一个retVal(得到的阈值(在后面一个方法中会用到)),第二个就是阈值化后的图像。
cvCvtColor(...)是Opencv里的颜色空间转换函数,可以实现RGB颜色向HSV,HSI等颜色空间的转换,也可以转换为灰度图像。参数CV_RGB2GRAY是RGB到gray。参数 CV_GRAY2RGB是gray到RGB.处理结果是彩色的,则转灰色就是了
运行效果如下:
3.7、边界框、最小矩形区域和最小闭圆的轮廓
找到一个正方形轮廓很简单,要找到不规则的、歪斜的以及旋转的形状可用 OpenCV的cv2.findContours函数,它能得到最好的结果,下面来看一幅图像:
现实的应用对目标的边界框、最小矩形面积、最小闭圆特别感兴趣。将cv2.findContours函数与少量的OpenCV的功能想结合就能非常容易地实现这些功能。
绘制矩形
函数:cv2.rectangle(img,(380,0),(511,111),(255,0,0),3),需要确定的就是矩形的两个点(左上角与右下角),颜色,线的类型(不设置就默认)
import cv2
import numpy as np
import os
from matplotlib import pyplot as plt
img = np.zeros((512,512,3),np.uint8) #生成一个空彩色图像
cv2.rectangle(img,(20,20),(411,411),(0,255,0),5)
plt.imshow(img,''brg'')
plt.show()
import cv2
import numpy as np
import os
img = cv2.pyrDown(cv2.imread("hammer.png", cv2.IMREAD_UNCHANGED))
ret, thresh = cv2.threshold(cv2.cvtColor(img.copy(), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)
contours, hier = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
# find bounding box coordinates
# 现计算出一个简单的边界框
x, y, w, h = cv2.boundingRect(c) # 将轮廓信息转换成(x, y)坐标,并加上矩形的高度和宽度
cv2.rectangle(img, (x,y), (x+w, y+h), (0, 255, 0), 2) # 画出矩形
# find minimum area
# 计算包围目标的最小矩形区域
rect = cv2.minAreaRect(c)
# calculate coordinate of the minimum area rectangle
box = cv2.boxPoints(rect)
# normalize coordinates to integers
box =np.int0(box)
# 注:OpenCV没有函数能直接从轮廓信息中计算出最小矩形顶点的坐标。所以需要计算出最小矩形区域,
# 然后计算这个矩形的顶点。由于计算出来的顶点坐标是浮点型,但是所得像素的坐标值是整数(不能获取像素的一部分),
# 所以需要做一个转换
# draw contours
cv2.drawContours(img, [box], 0, (0, 0, 255), 3) # 画出该矩形
# calculate center and radius of minimum enclosing circle
(x, y), radius = cv2.minEnclosingCircle(c) # 会返回一个二元组,第一个元素为圆心的坐标组成的元组,第二个元素为圆的半径值。
# cast to integers
center = (int(x), int(y))
radius = int(radius)
# draw the circle
img = cv2.circle(img, center, radius, (0, 255, 0), 2)
cv2.drawContours(img, contours, -1, (255, 0, 0), 1)
cv2.imshow("contours", img)
cv2.waitKey()
cv2.destroyAllWindows()
在导入模块后,加载图像,然后在源图像的灰度图像上执行一个二值化操作。这样做之后,可在这个灰度图像上执行所有计算轮廓的操作,但在源图像上可利用色彩信息来画这些轮廓。
cv2.drawContours(img, [box], 0, (0, 0, 255), 3):首先,该函数与所有绘图函数一样,它会修改源图像。其次,该函数的第二个参数接收一个保存着轮廓的数组,
从而可以在一次操作中绘制一系列的轮廓。因此如果只有一组点来表示多边形轮廓,就需要把这组点放到一个数组里。该函数的第三个参数是要绘制的轮廓数组的索引:-1表示绘制所有的轮廓,
否则只会绘制轮廓数组里指定的轮廓。大多数绘图函数把绘图的颜色和密度(thickness)放在最后两个参数里。
函数介绍:
cv2.imread():读入图片,共两个参数,第一个参数为要读入的图片文件名,第二个参数为如何读取图片,包括cv2.IMREAD_COLOR:读入一副彩色图片;
cv2.IMREAD_GRAYSCALE:以灰度模式读入图片;cv2.IMREAD_UNCHANGED:读入一幅图片,并包括其alpha通道。cv2.imread(''flower.jpg'',0)表示已灰度模式读入
cv2.imshow():创建一个窗口显示图片,共两个参数,第一个参数表示窗口名字,可以创建多个窗口中,但是每个窗口不能重名;第二个参数是读入的图片。
cv2.waitKey():键盘绑定函数,共一个参数,表示等待毫秒数,将等待特定的几毫秒,看键盘是否有输入,返回值为ASCII值。如果其参数为0,则表示无限期的等待键盘输入。
cv2.destroyAllWindows():删除建立的全部窗口
cv2.destroyWindows():删除指定的窗口。
cv2.imwrite():保存图片,共两个参数,第一个为保存文件名,第二个为读入图片
Opencv中可以通过函数cv2.pyrDown()和cv2.pyrUp()来构建金字塔。
函数cv2.pyrDown()是从一个高分辨率图像变成低分辨率图像的。cv2.pyrDown()函数接受3个参数:
tmp: 当前图像,初始化为原图像 src 。
dst: 目的图像( 显示图像,为输入图像的一半)
Size( tmp.cols/2, tmp.rows/2 ) :目的图像大小, 既然我们是向下采样
凸轮廓与Douglas-Peucker算法
大多数处理轮廓的时候,物体的形状(包括凸形状)都是变化多样的。凸形状内部的任意两点之间的连线都在该形状里面。
cv2.approxPloyDP是一个OpenCV函数,它用来计算近似的多边形框。该函数有三个参数:
第一个参数为“轮廓”;
第二个参数为“ε值”,它表示源轮廓与近似多边形的最大差值(这个值越小,近似多边形与源轮廓越接近);
第三个参数为“布尔标记”,它表示这个多边形是否闭合。
ε值对获取有用的轮廓非常重要。是为所得到的近似多边形周长与源轮廓周长之间的最大差值,这个差值越小,近似多边形与源轮廓就越相似。
可通过OpenCV的cv2.arcLength函数来得到轮廓的周长信息。
epsilon = 0.01 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
可通过OpenCV来有效地计算一个近似多边形,多边形周长与源轮廓周长之比就为ε。
为了计算凸形状,需要用OpenCV的cv2.convexHull函数来获取处理过的轮廓信息,代码为:
hull = cv2.convexHull(cnt)
3.8、直线和圆检测
Hough变换是直线和形状检测背后的理论基础。
绘制直线
函数为:cv2.line(img,Point pt1,Point pt2,color,thickness=1,line_type=8 shift=0)
有值的代表有默认值,不用给也行。可以看到这个函数主要接受参数为两个点的坐标,线的颜色(彩色图像的话颜色就是一个1*3的数组)
import cv2
import numpy as np
import os
from matplotlib import pyplot as plt
img = np.zeros((512,512),np.uint8)#生成一个空灰度图像
cv2.line(img,(0,200),(511,511),255,5)
plt.imshow(img,''gray'')
plt.show()
import cv2
import numpy as np
import os
from matplotlib import pyplot as plt
img = np.zeros((512,512,3),np.uint8)#生成一个空彩色图像
cv2.line(img,(200,0),(511,511),(0,255,0),5)
plt.imshow(img,''brg'')
plt.show()
3.9、直线检测
直线检测可通过HoughLines和HoughLinesP函数来完成,它们仅有的差别是:第一个函数使用标准的Hough变换,第二个函数使用概率Hough变换。HoughLinesP函数之所以成为
概率版本的Hough变换是因为它只通过分析点的子集并估计这些点都属于一条直线的概率,这是标准Hough变换的优化版本,该函数的计算代价会少一些,执行会变得更快。
import cv2
import numpy as np
img = cv2.imread("lines.png")
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 120)
minLineLength = 20
maxLineGap = 5
lines = cv2.HoughLinesP(edges, 1, np.pi/180, 100, minLineLength, maxLineGap)
for x1, y1, x2, y2 in lines[0]:
cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)
cv2.imshow("edges", edges)
cv2.imshow("lines", img)
cv2.waitKey()
cv2.destroyAllWindows()
HoughLines函数会接收一个由Canny边缘检测滤波器处理过的单通道二值图像,不一定需要Canny滤波器,但是一个经过去噪并只有边缘的图像当作Hough变换的输入会很不错。
HoughLinesP的参数:
需要处理的参数;
线段的几何表示rho和theta,一般分别取1和np.pi/180;
阈值,低于该阈值的直线会被忽略,Hough变换可以理解为投票箱和投票数之间的关系,每一个投票箱代表一个直线,投票数达到阈值的直线会被保留,其他的会被删除。
minLineLength和maxLineGap
3.10、绘制圆
绘制圆形只需要确定圆心与半径,函数: cv2.circle (img,(380,0),63,(255,0,0),3),
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = np.zeros((512,512,3),np.uint8)#生成一个空彩色图像
cv2.circle(img,(100,100),50,(55,255,155),5)
plt.imshow(img,''brg'')
plt.show(
3.11、圆检测
OpenCV的HoughCircles函数可用来检测圆,它与使用HoughLines函数类似。像用来决定删除或保留直线的两个参数minLineLength和maxLineGap一样,
HoughCircles有一个圆心间的最小距离和圆的最小及最大半径。
import cv2
import numpy as np
planets = cv2.imread("planet_glow.png")
gray_img = cv2.cvtColor(planets, cv2.COLOR_BGR2GRAY)
img = cv2.medianBlur(gray_img, 5)
cimg = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, 1, 120, param1=100, param2 = 30, minRadius = 0, maxRadius = 0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv2.circle(planets, (i[0], i[1]), i[2],(0, 255, 0),2)
# draw the center of the circle
cv2.circle(planets, (i[0], i[1]), 2, (0, 0,255), 3)
cv2.imwrite("planets_circles.jpg",planets)
cv2.imshow("HoughCircles", planets)
cv2.waitKey()
cv2.destroyAllWindows()
3.12、绘制椭圆
椭圆涉及到长轴短轴,椭圆圆心,旋转角度等。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = np.zeros((512,512,3),np.uint8)#生成一个空彩色图像
cv2.ellipse(img,(256,256),(150,100),0,0,180,250,-1)
#注意最后一个参数-1,表示对图像进行填充,默认是不填充的,如果去掉,只有椭圆轮廓了
plt.imshow(img,''brg'')
plt.show()
3.13、检测其他形状
Hough变换能检测的形状仅限于圆,前面提到过检测任何形状的方法,特别是用approxPloyDP函数来检测,该函数提供多边形的近似,所以如果你的图像有多边形,再结合cv2.findContours函数和
cv2.approxPloyDP函数,就能相当准确地检测出来。
OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像一
本文的内容都与图像处理有关,这时需要修改图像,比如要使用具有艺术性的滤镜、外插(extrapolate)某些部分、分割、粘贴或其他需要的操作。
1、不同色彩空间的的转换
OpenCV有数百种关于在不同色彩空间之间转换的方法。当前,计算机视觉中有三种常用的色彩空间:灰度、BGR以及HSV(Hue,Saturation,Value)。
灰度色彩空间是通过去除彩色信息来将其转换成灰阶,灰度色彩空间对中间处理特别有效,比如人脸检测。
BGR,即蓝-绿-红色彩空间,每一个像素点都由一个三元数组来表示,分别代表蓝、绿、红三种颜色。
HSV,H(Hue)是色调、S(Saturation)是饱和度、V(Value)表示黑暗的程度(或光谱另一端的明亮程度)。
BGR的简短说明
当第一次处理BGR色彩空间的时候,可以不要其中的一个色彩分量,比如像素值(0,255,255)(没有蓝色,绿色分量取最大值,红色分量取最大值)表示黄色,绿色和红色混合产生浑浊的褐色,
这是因为计算所使用的颜色模型具有可加性并且处理的是光照,而绘画不是这样(它遵从建色模型(subtractive color model))。计算机使用显示器发光来做颜色的媒介,
因此运行在计算机的软件所使用的色彩模型是加色模型。
2、佛里叶变换
在OpenCV中,对图像和视频的大多数处理都或多或少会涉及佛里叶变换的概念。Joseph Fourier(约瑟夫.佛里叶)是一位18实际的法国数学家,他发现并推广了很多数学概念,
主要研究热学规律,在数学上,他认为一切都可以用波形来描述。具体而言,他观察到的所有波形都可以由一系列简单其频率不同的正弦曲线叠加得到。也就是说,
人们看到的波形都是由其它波形叠加得到的。这个概念对操作图像非常有帮助,因为这样我们就可以区分图像里哪些区域的信号(比如图像像素)变化特别强,哪些区域的信号变化不那么强,
从而可以任意地标记噪声区域、感兴趣区域、前景和背景等。原始图像有许多频率组成,人们能够分离这些频率来处理图像和提取感兴趣的数据。
注意:在OpenCV环境中,有许多实现了算法让我们能够处理图像,理解图像中所包含的含义。这些算法在 NumPy中也有实现,而且更容易使用。NumPy有快速佛里叶变换(FFT)的包,
它包含了fft2()函数,此函数可以计算一副图像的离散佛里叶变换(DFT)。
下面通过介绍佛里叶变换来介绍图像的幅度谱(magnitude spectrum)。图像的幅度谱是另一种图像,幅度谱图像呈现了原始图像在变化方面的一种表示:把一副图像中最明亮的像素放到图中央,
然后逐渐变暗,在边缘的像素最暗。这样可以发现图像中有多少亮的像素和暗的像素,以及他们分布的百分比。
佛里叶变换的概念是许多常见的图像处理操作的基础,比如边缘检测或线段的和形状检测。
下面先介绍两个概念:高通滤波器和低通滤波器,上面提到那些操作都是以这两个概念和佛里叶变换为基础。
2.1、高通滤波器
高通滤波器(High-pass filter:HPF)是监测图像的某个区域,然后根据像素与周围像素的亮度差值来提示(boost)该像素的亮度的滤波器。
以如下的核(kernel)为例:
注意:核是指一组权重的结合,它会应用在源图像的一个区域,并由此产生目标图像的一个像素。比如,大小为7的核意味着每49(7*7)个源图像的像素会产生目标图像的一个像素。
可以把核看作一块覆盖在源图像上可以移动的毛玻璃片,玻璃片覆盖区域的光线会按某种方式进行扩散混合后投过去。
在计算完中央像素和周围临近像素的亮度差值之和以后,如果亮度变化很大,中央像素的亮度会增加(反之则不会)。换句话说,如果一个像素比它周围的像素突出,就会提示它的高度。
这在边缘检测上尤其有效,它会采用一种称为高频提示滤过器(high boost filger)的高通滤波器。
高通和低通滤波器都有一个称为半径(radius)的属性,它决定了多大面积的临近像素参与滤波运算。
下面是一个高通滤波器的例子:
import cv2
import numpy as np
import os
from scipy import ndimage
kernal_3x3 = np.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
kernal_5x5 = np.array([[-1, -1, -1, -1, -1],
[-1, 1, 2, 1, -1],
[-1, 2, 4, 2, -1],
[-1, 1, 2, 1, -1],
[-1, -1, -1, -1,-1]])
# 注意这些滤波器里面的值加起来等于0,以后会解释这个原因
# 使用函数cv2.imread() 读入图像。这幅图像应该在此程序的工作路径,或者给函数提供完整路径,第二个参数是要告诉函数应该如何读取这幅图片。
# • cv2.IMREAD_COLOR:读入一副彩色图像。图像的透明度会被忽略,这是默认参数。
# • cv2.IMREAD_GRAYSCALE:以灰度模式读入图像
img = cv2.imread(''flower.jpg'',0) # 注:此处后面要加上0,表示已灰度模式读入图像
k3 = ndimage.convolve(img, kernal_3x3) # 注:使用ndimage.convolve()时,滤波核的维度应与原始图像的维度相同,故此采用灰度图
k5 = ndimage.convolve(img, kernal_5x5)
blurred = cv2.GaussianBlur(img, (11, 11), 0)
g_hpf = img - blurred
cv2.imshow("flower", img)
cv2.imshow("flower:3x3", k3)
cv2.imshow("flower:5x5", k5)
cv2.imshow("flower:g_hpf", g_hpf)
cv2.waitKey()
cv2.destroyAllWindows()
运行效果图如下:
导入模块以后,我们定义了一个3*3和一个5*5的核,然后将读入的图像转换为灰度格式。通常大多数的图像处理会用NumPy来完成,但是这里的情况比较特殊,
因为需要一个给定的核与图像进行“卷积”(convolve),但是NumPy碰巧只接受一维数组。但是并不是说不能用NumPy完成多维数组的卷积运算,只是有些复杂。而ndimage(它是SciPy的
一部分)的convolve()函数可以解决这个问题,该函数支持经典的NumPy数组,cv2模块用这种数组来存储图像。
上面的代码用了两个自定义的卷积核来实现两个高通滤波器。最后会用一周不同的方法来实现一个高通滤波器:通过对象图像应用低通滤波器之后,与原始图像计算差值。第三种方法得到的效果最好。
2.2、低通滤波器
高通滤波器是根据像素与周围像素的亮度差值来提示该像素的亮度,低通滤波器(Low Pass Filter,LPF)则是在像素与周围像素的亮度差值小于一个特定值时,平滑该像素的亮度。
它主要用于去噪和模糊化,比如数,高斯模糊是最常用的模糊滤波器(平滑滤波器)之一,它是一个削弱高频信号强度的低通滤波器。
3、边缘检测
边缘在人类视觉和计算机视觉中均起着重要的的作用。人类能够凭借一张背景剪影或一个草图就识别出物体的类型和姿态。事实上,艺术强调边缘和姿态,
它们通常传达了原型(archetype)的思想,比如Rodin的《思考者》和Joe Shuster的《超人》。软件也一样,它可以推理出边缘、姿态以及原型。
OpenCV提供了许多边缘检测滤波函数,包括Laplacian()、Sobel()以及Scharr()。这些滤波函数都会将边缘区域转为黑色,将边缘区域转为白色或其它饱和的颜色。但是,
这些函数很容易将噪声错误地识别为边缘。缓解这个问题的办法是在找到边缘之前对图像进行模糊处理。OpenCV也提供了许多模糊滤波函数,包括blur()(简单是算术平均),medianBlur()以及
GaussianBlur()。边缘检测函数和模糊滤波函数有很多参数,但总会有一个ksize参数,它是一个奇数,表示高滤波的宽和高(以像素为单位)。
这里使用medianBlur()作为模糊函数,它对去除数字化的视频噪声非常有效,特别是去除彩色图像的噪声;使用Laplacian()作为边缘检测函数,它会产生明显的边缘线条,
灰度图像更是如此。在使用medianBlur()函数之后,将要使用Laplacian()函数之前,需要将图像从BGR色彩空间灰度色彩空间。
在得到Laplacian()函数的结果之后,需要将其转换成黑色边缘和黑色背景的图像。然后将其归一化(使它的像素值在0到1之间),并乘以源图像以便将边缘变黑。
代码实现如下:
def strokeEdges(src,dst,blurKsize = 7,edgeKsize = 5):
if blurKsize >= 3:
blurredSrc = cv2.medianBlur(src,blurKsize)
graySrc = cv2.cvtColor(blurredSrc, cv2.COLOR_BGR2GRAY)
else:
graySrc = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
cv2.Laplacian(graySrc,cv2.CV_8U,graySrc,ksize=edgeKsize)
normalizedInverseAlpha = (1.0/255)*(255-graySrc)
channels = cv2.split(src)
for channel in channels:
channel[:] = channel * normalizedInverseAlpha
cv2.merge(channels,dst)
注意,核的大小可由strokeEdges()函数的参数来指定。 blurKsize参数会作为medianBlur()函数的ksize参数,edgeKsize参数会作为Laplacian()函数的ksize参数。这里将blurKsize值设为7,
将edgeKsize值设为5会得到更好的效果,不幸的是,对于较大的ksize(比如7),使用medianBlur()的代价很高。
提示,如果你在使用strokeEdges()时遇到性能问题,可以试着减少blurKsize的值,要关闭模糊效果,可以将blurKsize的值设为3以下。
4、用定制内核做卷积
OpenCV预定义的许多滤波器(滤波函数)都使用核。其实核是一组权重,它决定如何通过临近像素点来计算新的像素点。核也称为卷积矩阵,它对一个区域的像素做调和
(mix up)或卷积运算,通常基于核的滤波器被称为卷积滤波器。
OpenCV提供了一个非常通用的filter2D(),它运用由用户指定的任意核或卷积矩阵。为了理解这个函数的使用方法,首先来了解卷积矩阵的的格式。卷积矩阵是一个二维数组,
有奇数行、奇数列,中心的元素对应于感兴趣的像素,其它的元素对应于这个像素周围的临近像素,每个元素都有一个整数或浮点数的值,这些值就是应用在像素上的权重。
kernel = numpy.array([[-1, -1 , -1],
[-1, 9, -1],
[-1, -1, -1]])
比如:上面实例在感兴趣的像素权重是9,其临近像素权重为-1。对感兴趣的像素来说,新像素值是用当前像素值乘以9,然后减去8个临近像素值。如果感兴趣的像素已经与临近
像素有一点差别,那么这个差别会增加,这些会让图像锐化,因为该像素的值与临近像素的之间的差距拉大了。注意权重加起来为1,如果不想改变图像的亮度就应该这样。
如果稍微修改一下锐化核使它的权重加起来为0,就会得到一个边缘检测核,把边缘转为白色,把非边缘区域转为黑色。
在源图像和目标图像上分别使用卷积矩阵:cv2.filter2D(src, -1, kernel, dst). 第二个参数指定了目标图像每个通道的位深度(比如,位深度cv2.CV_8U表示每个通道为8位),
如果为负值,则表示目标图像和源图像有同样的位深度。
注:对彩色图像来说,filter2D()会对每个通道都用同样的核。如果要对每个通道使用不同的核,就必须用split()函数和merge()函数。
对于模糊滤波器,为了达到模糊效果,通常权重和应该为1,而且邻近像素的权重全为正。
# VConvolutionFilter 表示一般的滤波器
class VConvolutionFilter(object):
"""A filter that applies a convolution to V(or all of BGR)."""
def __init__(self, kernel):
self._kernel = kernel
def apply(self, src, dst):
"""Apply the filter with a BGR or gray source/destination."""
cv2.filter2D(src, -1, self._kernel, dst)
# SharpenFilter 表示特定的锐化滤波器
class SharpenFilter(VConvolutionFilter):
"""A sharpen filter with a 1-pixel radius."""
def __init__(self):
kernel = numpy.array([[-1, -1, -1],
[-1, 9, -1],
[-1, -1, -1]])
VConvolutionFilter.__init__(self, kernel)
# 边缘检测滤波器
class FindEdgesFilter(VConvolutionFilter):
"""A edge-finding filter with a 1-pixel radius."""
def __init__(self):
kernel = numpy.array([[-1, -1, -1],
[-1, 8, -1],
[-1, -1, -1]])
VConvolutionFilter.__init__(self, kernel)
# 邻近平均滤波器
class BlurFilter(VConvolutionFilter):
"""A edge-finding filter with a 1-pixel radius."""
def __init__(self):
kernel = numpy.array([[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04],
[0.04, 0.04, 0.04, 0.04, 0.04]])
VConvolutionFilter.__init__(self, kernel)
锐化、边缘检测以及模糊等滤波器都是用了高度对称的核。但是有时不对称的核也会得到一些有趣的效果。
class EmbossFilter(VConvolutionFilter):
"""A edge-finding filter with a 1-pixel radius."""
def __init__(self):
kernel = numpy.array([[-2, -1, 0],
[-1, 1, 1],
[0, 1, 2]])
VConvolutionFilter.__init__(self, kernel)
我们今天的关于使用OpenCV Python提取所有边界框和python opencv边缘提取的分享就到这里,谢谢您的阅读,如果想了解更多关于c – OpenCV边界框、opencv-python-学习笔记二(利用opencv绘图)、OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像2、OpenCV3 for python3 学习笔记3-----用OpenCV3处理图像一的相关信息,可以在本站进行搜索。
本文标签: