1.图片的读取与保存
# -*- coding: utf-8 -*-
# @Author: Xingmo
import cv2
import numpy as np
# 读取图片: cv2.imread(路径,num) 其中num=0,为灰度图像;num=1为彩图
img = cv2.imread('002.jpg',0)
# 创建窗口,cv2.namedWindow(窗口名)
cv2.namedWindow('image')
# 保存图片,cv2.imwrite(保存图片名,要保存的图片)
cv2.imwrite('002.jpg',img)
# 第三个参数针对特定的格式: 对于JPEG,其表示的是图像的质量,用0-100的整数表示(越高越清晰,压缩级别越低),默认为95。 注意,cv2.IMWRITE_JPEG_QUALITY类型为Long,必须转换成int。
cv2.imwrite('003.jpg',img,[int(cv2.IMWRITE_JPEG_QUALITY), 10])
# 对于PNG,第三个参数表示的是压缩级别。cv2.IMWRITE_PNG_COMPRESSION,从0到9,压缩级别越高,图像尺寸越小。默认级别为3
cv2.imwrite('004.png', img, [int(cv2.IMWRITE_PNG_COMPRESSION), 5])
# 图片显示,cv2.imshow(窗口名,要显示的图片)
cv2.imshow('image1',img)
# 复制img图片
#emptyimage = img.copy()
# 创建空图片
emptyimage = np.zeros(img.shape,np.uint8)
cv2.imshow('image2',emptyimage)
# 键盘绑定函数
cv2.waitKey(0)
# 释放窗口
cv2.destroyAllWindows()
# -*- coding: utf-8 -*-
# @Author: Xingmo
import cv2
import numpy as np
# 添加椒盐噪声
def salt(img):
for k in range(100):
# 建立图片随机坐标点
i = int(np.random.random()*img.shape[0])
j = int(np.random.random()*img.shape[1])
# 图片为灰度图像,有二维
if img.ndim == 2:
img[i,j] = 255
# 图片为彩色图片,有三维,RGB
elif img.ndim == 3:
img[i,j,0] = 255
img[i,j,1] = 255
img[i,j,2] = 255
return img
if __name__ == '__main__':
# 读取图片
img = cv2.imread('001.jpg')
# 添加噪声
saltImage = salt(img)
# 图片显示
cv2.imshow("Salt", saltImage)
# 图片保存
cv2.imwrite('salt.jpg',saltImage)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.彩色图片各通道分离与合并
# -*- coding: utf-8 -*-
# @Author: Xingmo
import cv2
img = cv2.imread('001.jpg')
# split 返回BGR三个通道
b,g,r = cv2.split(img)
# merged 通道合并
merge = cv2.merge([b,g,r])
cv2.imshow('merge',merge)
#cv2.imshow("Red", r)
#cv2.imshow("Green", g)
#cv2.imshow("Blue", b)
cv2.waitKey(0)
cv2.destroyAllWindows()
4.直方图的绘画
# -*- coding: utf-8 -*-
# @Author: Xingmo
####### 说明 #######
# cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) #返回hist
# 第一个参数为读取的图像,必须用方括号括起来。
# 第二个参数是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道;
# 第三个参数是Mask,这里没有使用,所以用None。
# 第四个参数是histSize,表示这个直方图分成多少份(即多少个直方柱)。第二个例子将绘出直方图,到时候会清楚一点。
# 第五个参数是表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。
# 最后是两个可选参数,由于直方图作为函数结果返回了,所以第六个hist就没有意义了(待确定)
# 最后一个accumulate是一个布尔值,用来表示直方图是否叠加。
#######
# cv.PolyLine(img, polys, is_closed, color, thickness=1, lineType=8, shift=0) # 返回None
# img 读取的图像
# polys 多边形曲线的数组(各个坐标点)
# is_closed 绘制的折线是否关闭的标志,起始点是否有线连接,False为没有
# color 折线的颜色 [b,g,r]
# thickness 折线边缘的厚度
# lineType 线段的类型
# shift 顶点坐标中的小数位数
######## 说明END #######
import cv2
import numpy as np
# 将直方图(填充)转化为图片
def calcAndDrawHist(image, color):
hist = cv2.calcHist([image], [0], None, [256], [0.0,255.0])
# cv2.minMaxLoc 最大值maxVal和最小值minVal及它们的位置
minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)
# 创建全零图像
histImg = np.zeros([256,256,3], np.uint8)
hpt = int(0.95* 256);
for h in range(256):
# hpt=0.95*256 0.95防止最大值为整张图片的高,每个hist与最大值的比*(256*0.95)即可表示该hist在图片中的高度
intensity = int(hist[h]*hpt/maxVal)
# cv2.line(图像img,第一个点坐标(x1,y1),第二个点坐标(x2,y2),颜色[b,g,r])
cv2.line(histImg,(h,256), (h,256-intensity), color)
return histImg
# 将直方图(折线)转化为图片
def DrawHist(img):
# 建立空图片
h = np.zeros((256,256,3))
# 直方图中各bin的顶点位置
bins = np.arange(256).reshape(256,1)
# BGR三种颜色
color = [ (255,0,0),(0,255,0),(0,0,255) ]
for ch, col in enumerate(color):
originHist = cv2.calcHist([img],[ch],None,[256],[0,256])
# cv2.normalize(图像img,输出图像,归一化后最低值,归一化后最大值,规范化类型 cv2.NORM_MINMAX:仅针对密集阵列)
cv2.normalize(originHist, originHist,0,255*0.9,cv2.NORM_MINMAX)
# np.around(array) 取整数,但数据类型仍为float
hist=np.int32(np.around(originHist))
# np.column_stack 将两个1-D数组作为列堆叠成2维数组
pts = np.column_stack((bins,hist))
# cv2.polylines(图像img,多边形曲线的数组,绘制的折线是否关闭的标志,折线颜色)
cv2.polylines(h,[pts],False,col)
# np.flipud 在上/下方向翻转数组。
h=np.flipud(h)
return h
'''
####### 灰度图像———直方图(填充) #######
img = cv2.imread('001.jpg',0)
histimg = calcAndDrawHist(img,[255,255,255])
cv2.imshow('hist',histimg)
cv2.waitKey(0)
'''
####### 彩色图像———直方图(填充) #######
if __name__ == '__main__':
# 读取图片
img = cv2.imread("001.jpg")
# cv2.spilt 返回BGR三个通道
b, g, r = cv2.split(img)
# calcAndDrawHist(图像img,color填[b,g,r])
histImgB = calcAndDrawHist(b, [255, 0, 0])
histImgG = calcAndDrawHist(g, [0, 255, 0])
histImgR = calcAndDrawHist(r, [0, 0, 255])
cv2.imshow("histImgB", histImgB)
cv2.imshow("histImgG", histImgG)
cv2.imshow("histImgR", histImgR)
cv2.imshow("Img", img)
####### 彩色图像———直方图(折线) #######
if __name__ == '__main__':
img = cv2.imread("001.jpg")
h = DrawHist(img)
cv2.imshow('colorhist',h)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果显示:
彩色图像———直方图(填充)
彩色图像———直方图(折线)
5.形态学运算:膨胀与腐蚀
# -*- coding: utf-8 -*-
# @Author: Xingmo
import cv2
import numpy as np
# 读取图像
img = cv2.imread('004.jpg',0);
# 构造一个3×3的结构元素
element = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3))
# 膨胀图像 cv2.dilate(图像,元素结构)
dilate = cv2.dilate(img, element)
# 腐蚀图像 cv2.erode(图像,元素结构)
erode = cv2.erode(img, element)
# 将两幅图像相减获得边,第一个参数是膨胀后的图像,第二个参数是腐蚀后的图像
result = cv2.absdiff(dilate,erode);
# 上面得到的结果是灰度图,cv2.threshold将其二值化以便更清楚的观察结果
# cv2.threshold(src , thresh, maxval, type[, dst]) 返回retval、dst
# cv2.threshold(图像, 阈值 , 最大值, 阈值类型) 返回值类型、返回处理后图像
# 阈值类型:THRESH_BINARY、THRESH_BINARY_INV、THRESH_TRUNC、THRESH_TOZERO、THRESH_TOZERO_INV
retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY);
# 反色,即对二值图每个像素取反
result = cv2.bitwise_not(result);
# 显示图像
cv2.imshow("origin",img); # 原图
cv2.imshow("result",result);# 边缘检测图
cv2.waitKey(0)
cv2.destroyAllWindows()
结果显示:
6.初级滤波器
# -*- coding: utf-8 -*-
# @Author: Xingmo
import cv2
import numpy as np
######## 线性过滤器 #######
# 低通滤波(平滑图像)
# cv2.blur(图像,滤波器大小(num,num)) #返回dst(处理后图像)
#
# cv2.boxFilter(图像, -1, 滤波器大小(num,num)) #返回dst(处理后图像)
# 第二个参数-1表示与原图相同
#
# 高斯模糊
# cv2.GaussianBlur(图像,滤波器大小(num,num),X方向的高斯内核标准偏差) #返回dst(处理后图像)
######## 线性过滤器END #######
#
######## 非线性过滤器 #######
# 中值滤波
# cv2.medianBlur(图像,滤波器大小num)
####### 非线性过滤器END #######
def salt(img):
for k in range(100):
# 建立图片随机坐标点
i = int(np.random.random()*img.shape[0])
j = int(np.random.random()*img.shape[1])
# 图片为灰度图像,有二维
if img.ndim == 2:
img[i,j] = 255
# 图片为彩色图片,有三维,RGB
elif img.ndim == 3:
img[i,j,0] = 255
img[i,j,1] = 255
img[i,j,2] = 255
return img
if __name__ == '__main__':
#
img = cv2.imread('001.jpg',0)
salt =salt(img)
# 低通滤波
dst1 = cv2.blur(salt,(5,5))
# boxFilter
dst2 = cv2.boxFilter(salt,-1,(5,5))
# 高斯模糊
dst3 = cv2.GaussianBlur(salt,(5,5),1.5)
# 中值滤波
dst4 = cv2.medianBlur(salt,5)
# 图像显示
# 对于椒盐噪声而言,中值滤波效果是最好的,其他效果差不多
cv2.imshow('salt',salt)
cv2.imshow('blur',dst1)
cv2.imshow('boxFilter',dst2)
cv2.imshow('GaussianBlur',dst3)
cv2.imshow('medianBlur',dst4)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果显示:
7.sobel
# -*- coding: utf-8 -*-
# @Author: Xingmo
####### cv2.sobel说明 #######
# cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) #返回dst(处理后图像)
# scr 图像
# ddepth 输出图像深度
# S = 符号整型 U = 无符号整型 F = 浮点型
# src.depth()= CV_8U,ddepth= -1 / CV_16S/ CV_32F/CV_64F
# src.depth()= CV_16U/ CV_16S,ddepth= -1 CV_32F//CV_64F
# src.depth()= CV_32F,ddepth= -1 CV_32F/CV_64F
# src.depth()= CV_64F,ddepth= -1 /CV_64F
# 何时ddepth=-1,目的地图像将具有与源相同的深度
# dx
# dy
####### cv2.sobel说明END #######
import cv2
import numpy as np
img = cv2.imread('003.jpg', 0)
x = cv2.Sobel(img,cv2.CV_16S,1,0)
y = cv2.Sobel(img,cv2.CV_16S,0,1)
# cv2.convertScaleAbs 在输入数组的每个元素上,该函数依次执行三个操作:缩放,取绝对值,转换为无符号8位类型
# 转回uint8
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
# cv2.addWeighted(src1 , alpha, src2 , beta , gamma[, dst[, dtype]]) #返回dst(处理后图像)
# cv2.addWeighted(输入1, 分量1, 输入2, 分量2, 标量)
# dst = src1*alpha + src2*beta + gamma
dst = cv2.addWeighted(absX,0.5,absY,0.5,0)
# 图像显示
cv2.imshow('origin',img)
cv2.imshow("absX", absX)
cv2.imshow("absY", absY)
cv2.imshow("Result", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果显示:
8.laplacian
# -*- coding: utf-8 -*-
# @Author: Xingmo
####### cv2.Laplacian 说明 #######
# cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) #返回dst(处理后图像)
# src 图像
# ddepth 输出图像深度
# S = 符号整型 U = 无符号整型 F = 浮点型
# src.depth()= CV_8U,ddepth= -1 / CV_16S/ CV_32F/CV_64F
# src.depth()= CV_16U/ CV_16S,ddepth= -1 CV_32F//CV_64F
# src.depth()= CV_32F,ddepth= -1 CV_32F/CV_64F
# src.depth()= CV_64F,ddepth= -1 /CV_64F
# 何时ddepth=-1,目的地图像将具有与源相同的深度
# dst 输出图像
# ksize 用于计算二阶微分滤波器的孔径大小,其大小必须是正数和奇数
# scale 缩放导数的比例常数,默认情况下没有伸缩系数
# delta 在结果存储之前添加到结果中的可选增量值,默认情况下没有额外的值加到dst中
# borderType 判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT
####### cv2.Laplacian 说明END #######
import cv2
import numpy as np
# 图像读取
img = cv2.imread("004.jpg", 0)
gray_lap = cv2.Laplacian(img,cv2.CV_16S,ksize = 3)
# cv2.convertScaleAbs 在输入数组的每个元素上,该函数依次执行三个操作:缩放,取绝对值,转换为无符号8位类型
# 转回uint8
dst = cv2.convertScaleAbs(gray_lap)
# 图像显示
cv2.imshow('origin',img)
cv2.imshow('laplacian',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果显示:
由于laplacian对噪声敏感,对图片先去躁可得到更好的效果
blur = cv2.medianBlur(img,3)
blur = cv2.blur(img,(3,3))
此处有laplacain算法原理
9.canny
# -*- coding: utf-8 -*-
# @Author: Xingmo
####### cv2.Canny 说明 #######
# cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) 返回edges(边缘图)
# image 原图像,该图像必须为单通道的灰度图
# threshold1 第一个阈值
# threshold2 第二个阈值
# apertureSize Sobel算子的孔径大小,其有默认值3
# L2gradient 是否使用L2范数,一个计算图像梯度幅值的标识,默认值false
####### cv2.Canny 说明END #######
import cv2
import numpy as np
# 读取图片
img = cv2.imread('004.jpg', 0)
# 高斯模糊
blur = cv2.GaussianBlur(img,(3,3),0)
canny = cv2.Canny(blur, 50, 200)
# 图像显示
cv2.imshow('origin',img)
cv2.imshow('Canny', canny)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果显示: