一、Opencv-Python简介
Opencv-Python 是Python代码组合成的一个库,用来解决计算机视觉问题。
Python编程变得越来越流行的原因是它的简易性和代码可读性。Python可以通过写更少的代码来表达编程者的“想要做的事”,并且不失去代码的可读性。
与C/C++语言相比,Python确实相对比较慢。C/C++代码可以扩展至Python,也就是说,我们写的C/C++代码可以封装成Python包用于充当python模块。这可以有两个优势:1.这些扩展代码和原始的C/C++代码速度一样快。2.结合这些扩展代码,在Python中继续书写更加方便的代码。而Opencv-Python就是C++实践的Python包。
Opencv-Python使用Numpy库。Numpy库是matlab风格的,并在数字运算领域非常优秀的库。所有Opencv矩阵结构都是在Numpy矩阵之间转化,这能够很好地结合与利用起其他使用Numpy矩阵的库如SciPy和Matplotlib。
二、Image基本操作
1、 如何使用cv2.imread(),cv2.imshow(),cv2.imwrite()来读入、显示和保存一张图像。
cv2.imread()第一个参数需要给出读入图片所在的完整工作路径(不能有中文路径),第二个参数是图片读入的方式:cv2.IMREAD_COLOR(读入彩色图像),cv2.IMREAD_GRAYSCALE(读入灰度图),cv2.IMREAD_UNCHANGED(包含alpha通道的图像)。或者分别用数字1,0,-1代替。
import cv2
import numpy as np
img = cv2.imread('C:/Users/SLJ/Desktop/pic.jpg',cv2.IMREAD_GRAYSCALE)
cv2.namedWindow('Image',cv2.WINDOW_NORMAL)
cv2.imshow('Image',img)
cv2.waitKey(0)
cv2.imwrite('C:/Users/SLJ/Desktop/pic_another.jpg',img)
2、获取以及修改图像中像素点的值
px = img[200,200](获取(200,200)坐标点中的像素值);对于灰度图而言,img[200,200] = 255(将(200,200)坐标点中的像素值赋值为255);对于RGB图,img[i,j] = (b,g,r)。在C++中这一操作为int px = img.at<unsigned char>(200,200);img.at<unsigned char>(200,200) = 255。但以上读取已经赋值图像数据的方法并不好,Numpy是一个针对矩阵计算的一个优化库。如果只是简单获取每一个像素值或者修改它,使用这种方法会非常慢。
若对于图像中整一行赋值,可采用例如img[100,:] = 255,将img中第100行中的所有像素赋值为255。
3、获取图像中的属性
图像中的属性包括行、列、通道(height,width,channel) = img.shape;在C++中要获取信息一般是int height = img.rows,int width = img.cols,int channels = img.channels()。计算图像中所有的像素点:total_pixel = img.size。
4、获取图像ROI
ROI = img[500:2000,1000:2000],在C++中的方法为“Mat ROIImage = srcImage.rowRange(500,2000).colRange(1000,2000);”。在python中还可以将ROI贴到原图中img[600:2100,500:1500] = ROI,但在C++中就不可逆,需要用像素点填充的方法,因为同样“srcImage.rowRange(600, 2100).colRange(500, 1500) = ROIImage;”方法不管用。
import cv2
img = cv2.imread('IMG_2808.JPG',cv2.IMREAD_COLOR) # 读入图像
GrayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 将彩色图转化为灰度图
(height,width,channel) = img.shape # 计算图像的长宽通道信息(不支持灰度图像,灰度图像没有channel)
totalPixel = img.size # 图像所有的像素点
print(img.dtype) # 图像的存储格式
ROI = img[500:2000,1000:2000] # 截取图像的ROI
img[600:2100,500:1500] = ROI # 将ROI重新赋值到图像上
cv2.namedWindow('img',cv2.WINDOW_NORMAL) # 查看此时的图像
cv2.imshow('img',img)
cv2.waitKey(0)
px = GrayImage[100,200] # 获取图像的像素值
for i in range(500,2000): # 将图像上的一定的像素值置换(不推荐,速度非常慢)
for j in range(500,1000):
GrayImage[i,j] = 255
cv2.namedWindow('GrayImage',cv2.WINDOW_NORMAL) # 查看此时的图像
cv2.imshow('GrayImage',GrayImage)
cv2.waitKey(0)
三、Image计算操作
1、图片的相加
关于图片Image的相加方法有两种cv2.add(img1,img2),或者简单的numpy方法res = img1 + img2。这两种最终得到的计算方式不同print(cv2.add(x,y)) # 250+10 = 260 => 255(如果有溢出则该像素变为最大值255);print(x+y )# 250+10 = 260 % 256 = 4(如果有溢出则模256)。而addWeighted提供两幅图像权重相加dst = cv2.addWeighted(img1,0.7,img2,0.3,20)。当然还有图像相减操作。
2、图像取反Bitwise操作(AND, OR, NOT and XOR operations)
import cv2
img = cv2.imread('IMG_2808.JPG',cv2.IMREAD_COLOR) # 读入图像
GrayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 将彩色图转化为灰度图
ret,mask = cv2.threshold(GrayImage,100,255,cv2.THRESH_BINARY) # 灰度图像转化为二值图像
mask_inv = cv2.bitwise_not(mask) # 将整体二值图像取反
GrayImage_ADD1 = cv2.add(GrayImage,GrayImage) # 两张灰度相加,溢出取255
GrayImage_ADD2 = GrayImage + GrayImage # 两张灰度图像相加,溢出取余
dst = cv2.addWeighted(GrayImage,0.3,GrayImage_ADD1,0.7,20) # 两张灰度图像权重相加
cv2.namedWindow('ShowImage',cv2.WINDOW_NORMAL) # 查看此时的图像
cv2.imshow('ShowImage',mask_inv)
cv2.waitKey(0)
四、函数操作(举例)
1、自适应阈值法、寻找轮廓、绘制轮廓
# adaptive threshold
a_maxValue = 255
a_adaptiveMethod = 0
a_threType = 1
a_blockSize = 21
a_C = 21
thre_img = cv2.adaptiveThreshold(ROI, a_maxValue, a_adaptiveMethod, a_threType, a_blockSize, a_C)
# findContours
contours, hierarchy = cv2.findContours(thre_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
for cur_contour in contours:
cur_box = cv2.minAreaRect(cur_contour) # 获取轮廓的最小矩形
pts = cv2.boxPoints(cur_box) # 四个点表示最小矩形的轮廓
center_X, center_Y = cur_box[0] # 最小矩形的中心点
width, height = cur_box[1] # 最小矩形的长和宽
angle = cur_box[2] # 最小矩形的角度
radio_cols_rows = width / (height + 0.0001) # 筛选条件1
box_area = width * height # 筛选条件2
if radio_cols_rows > 0.5 and radio_cols_rows < 2.2 and box_area > 600 and box_area < 2500:
for j in range(4):
p_A = pts[j]
p_B = pts[(j+1) % 4]
cv2.line(ROI_show, (p_A[0], p_A[1]), (p_B[0], p_B[1]), (0, 0, 255))