OpenCV学习笔记

张开发
2026/4/12 0:29:25 15 分钟阅读

分享文章

OpenCV学习笔记
0403Record一、任务与目标圆边界提取和圆内数量提取误差万分之一4.10之前完成4月7日-4月10日把二中内容温习并完成以下任务批量读取文件夹图片并统一 resize裁剪指定 ROI 在图上画矩形框、圆和文字并保存。做一个二值化 形态学 Canny 轮廓 霍夫圆的脚本做一个轮廓提取并标面积/周长的小工具和一个圆或直线检测 demo二、代码及注释注代码注释即为详细的函数参数介绍00导入OpenCV库importcv2importnumpyasnp01读取图像img_pathD:/JCKJ/March/202510251/1.jpeg# 图像路径imgcv2.imread(img_path)#imread为图片读取函数ifimgisNone:raiseFileNotFoundError(图片读取失败请检查路径是否正确)print(type(img))#打印出图片格式类型为数组print(img.dtype)#打印出图片数据类型uint8取值范围是0-255img.shape#图像尺寸——灰度图(高, 宽)彩色图(高h, 宽w通道数c)02灰度化graycv2.cvtColor(img,cv2.COLOR_BGR2GRAY)print(type(gray))#打印出图片格式类型为数组gray.shape03查询像素img[1000,1200]#数组中每一个数字相当于一个像素用数组的方式查询img[y,x]数组中先写行再写列roiimg[y1:y2,x1:x2]#切片方式也是先y后x#背景为黑的感兴趣区域black_imgnp.zeros_like(gray)# 创建全黑的图像roigray[4000:5000,4500:5500].copy()# 选取感兴趣区域如果不想影响原图要.copy()black_img[4000:5000,4500:5500]roi# 将全黑图像中对应的感兴趣区域替换为原始的感兴趣区域output_pathD:/JCKJ/April/bool/1_roicopy.jpegcv2.imwrite(output_path,black_img)04图像中的布尔掩码maskgray100#创建一个布尔掩码mask将灰度值大于100的提取至数组bright_pixelsgray[mask]#提取到的像素存储在bright_pixelsgray[gray100]255#将所有大于100的设置成255白色output_pathD:/JCKJ/April/bool/1_first.jpegcv2.imwrite(output_path,gray)#cv2.imwrite() 函数接受两个参数第一个参数是保存图像的路径第二个参数是要保存的图像数据05圆形区域掩码masknp.zeros(gray.shape,dtypenp.uint8)#这里的mask是一个黑底白圆cv2.circle(mask,(cx,cy),r,255,-1)#注意这里的cxcy为圆形区域的圆心坐标r为半径circle_regioncv2.bitwise_and(gray,gray,maskmask)#保留圆形区域内的内容output_pathD:/JCKJ/April/bool/1_circle.jpegcv2.imwrite(output_path,circle_region)#第二个参数的图像数据是circle_region06通道b,g,rcv2.split(img)#拆通道bimg[:,:,0]gimg[:,:,1]rimg[:,:,2]#直接索引07卷积#本质上是用核也就是窗口来重新定义当前核或窗口的中心点blurcv2.GaussianBlur(gray,(5,5),0)#例如高斯模糊效果噪声平滑、平滑图像08resize缩放图像scale_factor0.5# 缩放因子调整大小#注意缩放时是先宽再高shape是高宽通道resized_graycv2.resize(gray,(int(gray.shape[1]*scale_factor),int(gray.shape[0]*scale_factor)))output_pathD:/JCKJ/April/bool/1_resized.jpegcv2.imwrite(output_path,resized_gray)09rotate旋转图像rot1cv2.rotate(gray,cv2.ROTATE_90_CLOCKWISE)#顺时针旋转90rot2cv2.rotate(gray,cv2.ROTATE_90_COUNTERCLOCKWISE)#逆时针旋转90rot3cv2.rotate(gray,cv2.ROTATE_180)#旋转180cv2.imwrite(D:/JCKJ/April/bool/rot1.jpeg,rot1)cv2.imwrite(D:/JCKJ/April/bool/rot2.jpeg,rot2)cv2.imwrite(D:/JCKJ/April/bool/rot3.jpeg,rot3)h,wimg.shape[:2]center(w//2,h//2)#图像像素宽高整除2得到旋转中心Mcv2.getRotationMatrix2D(center,30,1.0)#第一个是旋转中心第二个是旋转角度逆时针为正第三个是缩放系数rotcv2.warpAffine(img,M,(w,h))#经过前面计算得到的仿射变换矩阵cv2.imwrite(D:/JCKJ/April/bool/rot.jpeg,rot)10flip翻转图像flip_graycv2.flip(gray,1)#1是水平翻转0是垂直翻转-1是先垂直翻转再左右翻转#灰度转BGR和显示图像gray_bgrcv2.cvtColor(gray,cv2.COLOR_GRAY2BGR)importmatplotlib.pyplotasplt plt.imshow(img)#颜色可能会怪默认RGB#解决方法rgbcv2.cvtColor(img,cv2.COLOR_BGR2RGB)plt.imshow(rgb)11画框、画圆、写字cv2.rectangle(img,(100,200),(300,400),(0,0,255),2)#两个点为矩形的对角线坐标红色2为线宽-1代表填充cv2.circle(img,(6000,6000),4000,(255,0,0),-1)#同理圆心坐标和半径cv2.putText(img,84450,(8800,500),cv2.FONT_HERSHEY_SIMPLEX,20.0,(0,0,255),15)#图像写的内容坐标字体字号缩放颜色线宽12滤波blurcv2.blur(img,(3,3))#均值滤波窗口越大平滑越强细节丢失越多blurcv2.GaussianBlur(img,(5,5),0)#高斯滤波高斯核大小通常为奇数0为标准差越小保留的细节越多blurcv2.medianBlur(img,5)#中值滤波核大小必须为奇数13阈值处理#固定阈值_,binarycv2.threshold(gray,127,255,cv2.THRESH_BINARY)#一开始的_是Python中的一个写法用于表示一个临时变量即占位符。这是因为cv2.threshold函数会返回两个值第一个是阈值第二个是经过阈值处理后的图像#127为阈值满足条件时赋值为255这里就是大于127的像素最后的参数表示大于阈值变白#常见变种——反二值化_,binarycv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)#这里就是满足条件赋值也就是大于阈值变黑#Otsu阈值_,binarycv2.threshold(gray,0,255,cv2.THRESH_BINARYcv2.THRESH_OTSU)#会自动算阈值手动写的阈值基本不生效最后一个参数要结合固定阈值#自适应阈值binarycv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)#三参数局部加权平均法五参数局部窗口大小六参数从局部均值中减去的常数14形态学#通常要定义一个核kernelcv2.getStructuringElement(cv2.MORPH_RECT,(3,3))#矩形kernelcv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))#椭圆核erodedcv2.erode(binary,kernel,iterations1)#腐蚀dilatedcv2.dilate(binary,kernel,iterations1)#膨胀openedcv2.morphologyEx(binary,cv2.MORPH_OPEN,kernel)#开运算先腐蚀后膨胀closedcv2.morphologyEx(binary,cv2.MORPH_CLOSE,kernel)#闭运算先膨胀后腐蚀15边缘Cannyblurcv2.GaussianBlur(gray,(5,5),0)#提取边缘前先高斯滤波因为噪声会产生很多假边缘edgescv2.Canny(blur,50,150)#50是低阈值150是高阈值16轮廓findContourscontours,_cv2.findContours(binary,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#找轮廓cv2.drawContours(img,contours,-1,(0,0,255),2)#画轮廓这边的-1代表画全部轮廓areacv2.contourArea(contours)#轮廓面积perimetercv2.arcLength(contours,True)#轮廓周长x,y,w,hcv2.boundingRect(contours)#边界矩形(x,y),rcv2.minEnclosingCircle(contours)#最小外接圆17连通域num_labels,labels,stats,centroidscv2.connectedComponentsWithStats(binary)#连通域数量和原图同尺寸每个像素都被标记属于哪个连通域统计信息包括左上角的xy宽高面积连通域中心点坐标foriinrange(1,num_labels):# 0通常是背景xstats[i,cv2.CC_STAT_LEFT]ystats[i,cv2.CC_STAT_TOP]wstats[i,cv2.CC_STAT_WIDTH]hstats[i,cv2.CC_STAT_HEIGHT]areastats[i,cv2.CC_STAT_AREA]cx,cycentroids[i]#访问每个连通域18霍夫直线linescv2.HoughLines(edges,1,np.pi/180,150)#输入是Canny边缘图1是rho分辨率np.pi / 180是theta分辨率1度150是投票阈值越大越严格#概率霍夫直线更常用是因为它直接返回线段的两个端点方便画图和使用linescv2.HoughLinesP(edges,1,np.pi/180,80,minLineLength50,maxLineGap10)#minLineLength是最短线段长度maxLineGap是断开点之间允许的最大连接间隔#在图像上绘制线iflinesisnotNone:forlineinlines:x1,y1,x2,y2line[0]cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)19霍夫圆circlescv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,dp1.2,#累加器分辨率和原图分辨率的比值常见为1.0、1.2、1.5minDist50,#两个圆心最小距离防止同一个圆被重复检测param1100,#内部Canny的高阈值param230,#圆检测的阈值越大越严格检测到的圆越少minRadius20,maxRadius100#圆的半径范围)#画圆ifcirclesisnotNone:circlesnp.round(circles[0]).astype(int)forx,y,rincircles:cv2.circle(img,(x,y),r,(0,0,255),2)#检测霍夫圆之前通常要做灰度化和高斯滤波三、笔记照片

更多文章