一、认识图像 你需要选取任意一张图片做以下操作。1.分离出图像的三个通道(BGR)2.多图像进行色彩空间转换(不限定类型,至少两种)3.对你选择的图片进行不少于五种的图像处理操作(如形态学处理、仿射变换等等,其他的靠自己去探索学习) 这些效果都可以由opencv的函数实现,运行程序时都需要显示出来。
引入库
import cv2
import numpy as np
import matplotlib.pyplot as plt
1.分离出图像的三个通道(BGR)
def char_rgb(img):
b,g,r=cv2.split(img)
return cv2.merge([r,g,b])
img=cv2.imread(r'x.png')
b,g,r=cv2.split(img)
zeros = np.zeros(img.shape[:2], dtype = "uint8")
plt.subplot(221)
plt.title("blue")
merged = cv2.merge([zeros, zeros, b])
plt.axis("off")
plt.imshow(merged)
plt.subplot(222)
plt.title("green")
merged = cv2.merge([zeros, g, zeros])
plt.axis("off")
plt.imshow(merged)
merged = cv2.merge([r, zeros, zeros])
plt.subplot(223)
plt.title("red")
plt.axis("off")
plt.imshow(merged)
plt.subplot(224)
merged = cv2.merge([r, g,b])
plt.title("merge")
plt.axis("off")
plt.imshow(merged)
plt.show()
2.多图像进行色彩空间转换
plt.figure("色彩空间转换", figsize=(12, 8))
img=cv2.imread(r'x.png')
plt.subplot(221)
img1=img.copy()
hsv = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)
plt.title("hsv")
plt.axis("off")
plt.imshow(hsv[:,:,[2,1,0]])
plt.subplot(222)
img2=img.copy()
yuv = cv2.cvtColor(img2, cv2.COLOR_BGR2YUV)
plt.title("yuv")
plt.axis("off")
plt.imshow(yuv[:,:,[2,1,0]])
plt.subplot(223)
img3=img.copy()
ycrcb = cv2.cvtColor(img3,cv2.COLOR_BGR2YCrCb)
plt.title("ycrcb")
plt.axis("off")
plt.imshow(ycrcb[:,:,[2,1,0]])
plt.subplot(224)
img4=img.copy()
img = cv2.cvtColor(img4,cv2.COLOR_BGR2GRAY)
plt.title("gray")
plt.axis("off")
GRAY = np.concatenate((np.expand_dims(img, axis=2), np.expand_dims(img, axis=2), np.expand_dims(img, axis=2)), axis=-1)
plt.imshow(GRAY)
plt.show()
3.图像处理操作
###(1)形态学处理
#开运算
img=cv2.imread(r'x.png')
img1=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转为灰度图;
ret2, th2 = cv2.threshold(img1, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)#二值化处理
for i in range(2000): # 添加椒盐噪声
_x = np.random.randint(0, th2.shape[0])
_y = np.random.randint(0, th2.shape[1])
th2[_x][_y] = 255
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.morphologyEx(th2, cv2.MORPH_OPEN, kernel) # 开运算函数:先进行腐蚀再膨胀
plt.subplot(121)
plt.imshow(th2)
plt.axis('off')
plt.subplot(122)
plt.imshow(erosion)
plt.axis('off')
plt.show()
#闭运算
img=cv2.imread(r'x.png',0)
#img1=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)转为灰度图
ret2, th2 = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)#二值化处理
for i in range(20000): # 添加椒盐噪声
_x = np.random.randint(0, th2.shape[0])
_y = np.random.randint(0, th2.shape[1])
th2[_x][_y] = 0
kernel = np.ones((5, 5), np.uint8)
erosion = cv2.morphologyEx(th2, cv2.MORPH_CLOSE, kernel) # 闭运算函数:先进行膨胀再腐蚀
plt.subplot(121)
plt.imshow(th2)
plt.axis('off')
plt.subplot(122)
plt.imshow(erosion)
plt.axis('off')
plt.show()
# 寻找轮廓
img = cv2.imread(r'x.png', 0)
ret, th = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
kernel = np.ones((5, 5), np.uint8)
# morphology 形态学
gradient = cv2.morphologyEx(th, cv2.MORPH_GRADIENT,kernel) # morph gradient 形态梯度
plt.subplot(121)
plt.imshow(th)
plt.axis('off')
plt.subplot(122)
plt.imshow(gradient)
plt.axis('off')
plt.show()
###(2)仿射变换
img = cv2.imread(r'x.png')
h,w,c=img.shape
#缩小2倍
A1=np.array([[0.5,0,0],[0,0.5,0]],np.float32)
A2=cv2.warpAffine(img,A1,(w,h),borderValue=126)
#缩小后平移
B1=np.array([[0.5,0,w/4],[0,0.5,h/4]],np.float32)
B2=cv2.warpAffine(img,B1,(w,h),borderValue=126)
#使图像旋转
C1=cv2.getRotationMatrix2D((w/2.0,h/2.0),30,1)
C2=cv2.warpAffine(img,C1,(w,h),borderValue=126)
#仿射
p1 = np.float32([[0,0], [w-1,0], [0,h-1]])
p2 = np.float32([[0,h*0.3], [w*0.8,h*0.2], [w*0.15,h*0.7]])
M = cv2.getAffineTransform(p1, p2)
dst = cv2.warpAffine(img, M, (w,h))
plt.subplot(141)
plt.imshow(A2[:,:,[2,1,0]])
plt.axis('off')
plt.subplot(142)
plt.imshow(B2[:,:,[2,1,0]])
plt.axis('off')
plt.subplot(143)
plt.imshow(C2[:,:,[2,1,0]])
plt.axis('off')
plt.subplot(144)
plt.imshow(dst[:,:,[2,1,0]])
plt.axis('off')
plt.show
###(3)透视变换
img = cv2.imread(r'x.png')
rows, cols, channels = img.shape
p1 = np.float32([[0,0], [cols-1,0], [0,rows-1], [rows-1,cols-1]])
p2 = np.float32([[0,rows*0.3], [cols*0.8,rows*0.2], [cols*0.15,rows*0.7], [cols*0.8,rows*0.8]])
M = cv2.getPerspectiveTransform(p1,p2)
dst = cv2.warpPerspective(img, M, (cols, rows))
plt.subplot(141)
plt.imshow(dst[:,:,[2,1,0]])
plt.axis('off')
plt.show()
###(4)平滑处理
img = cv2.imread(r'x.png')
img1=img.copy()
for i in range(20000): # 添加椒盐噪声
_x = np.random.randint(0, img1.shape[0])
_y = np.random.randint(0, img1.shape[1])
img1[_x][_y] = 255
plt.subplot(151)
plt.title('origin')
plt.imshow(img1[:,:,[2,1,0]])
plt.axis('off')
plt.subplot(152)
plt.title('blur')
plt.imshow(cv2.blur(img1, (3, 3))[:,:,[2,1,0]])
plt.axis('off')
plt.subplot(153)
plt.title('Gaussian')
plt.imshow(cv2. GaussianBlur(img1, (5, 5),1)[:,:,[2,1,0]])
plt.axis('off')
plt.subplot(154)
plt.title('box')
plt.imshow(cv2.boxFilter(img,-1,(3,3), normalize=True) [:,:,[2,1,0]])
plt.axis('off')
plt.subplot(155)
plt.title('median')
plt.imshow(cv2.medianBlur(img, 5)[:,:,[2,1,0]])
plt.axis('off')
plt.show()
3.阈值操作
img = cv2.imread(r'x.png')
img = cv2.GaussianBlur(img, (3, 3), 1)
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)
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i][:,:,[2,1,0]])
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
二、形状探测 在下面这张图片(x.png)中找出直线、圆、椭圆等图形元素,并把他们用有颜色的线条标记出来。如果左下角点(绿色夹角处)到右下角点(绿色夹角处)的真实距离定为10cm,那么左下角点到最高点(绿色圆球处)的距离是多少?
# 读取彩色图片
img = cv2.imread(r'x.png')
# 转换为灰度图片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 进行二值化处理
ret,binary = cv2.threshold(gray, 224, 255, cv2.THRESH_BINARY_INV)
plt.subplot(121)
plt.imshow( binary)
plt.axis('off')
# 寻找轮廓
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制不同的轮廓
draw = cv2.drawContours(img.copy(),contours,-1,(0,255,255),3)
plt.subplot(122)
plt.imshow(draw[:,:,[2,1,0]])
plt.axis('off')
len(contours)
3
plt.subplot(131)
plt.imshow(cv2.drawContours(img.copy(),contours[0],-1,(0,255,255),3)[:,:,[2,1,0]])
plt.axis('off')
plt.subplot(132)
plt.imshow(cv2.drawContours(img.copy(),contours[1],-1,(0,255,255),3)[:,:,[2,1,0]])
plt.axis('off')
plt.subplot(133)
plt.imshow(cv2.drawContours(img.copy(),contours[2],-1,(0,255,255),3)[:,:,[2,1,0]])
plt.axis('off')
plt.show()
#故所需数据均在contours[2]中
list_a=np.squeeze(contours[2])
list_a = list_a[list_a[:,1].argsort()]
list_a.tolist()
min,max=list_a[0][0],list_a[0][0]
for i in list_a:
if i[1]<min:
min=i[1]
if i[1]>max:
max=i[1]
b=[]
for i in list_a:
if i[1]==max:
b.append(i[0])
b.sort()
x=10/(b[len(b)-1]-b[0])*np.sqrt((max-min)**2+(b[0]-img.shape[1]/2)**2)
print("实际距离:",x,"cm")