简单的图像处理
在这篇文章,将简要地分别通过MATLAB、Python、JavaScript来实现一些图像处理的基本操作
Python篇
获取图片的信息
图像的尺寸
import cv2
img = cv2.imread('test.jpg')
size = img.shape
print(size)
height,width,channels = img.shape
print(height,width,channels)
# 或者
from PIL import Image
img = Image.open('test.jpg')
imgSize = img.size
print(max(imgSize),min(imgSize))
图片缩放
samll_img = cv2.resize(src=img, dsize=None, fx=0.5, fy=0.5)
# 宽高缩小为原来的一半
复制图像
import cv2
import numpy as np
img = cv2.imread('test.jpg')
size = img.shape
im = np.zeros(img.shape, np.uint8)
# 也可以直接:
im = img.copy()
PIL图片和opencv图片相互转换
OpenCV to PIL:
pil = Image.fromarray(cv2.cvtColor(cv, cv2.COLORBGR2RGB))
PIL to OpenCV:
pil = PIL.Image.open('test.jpg').convert('RGB')
cv = numpy.array(pil)
cv = cv[:,:,::-1].copy()
灰度化
通过matplotlab库灰度化
首先安装matplotlab
库:sudo pip install matplotlib
import matplotlib.pyplot as plt
import matlotlib.image as mpimg
import numpy as np
img = mpimg.imread('test.jpg')
img.shape
# (282, 292, 3)
plt.axis('on') #显示坐标轴
plt.show() #显示原图片
def rgb2gray(rgb):
return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])
gray = rgb2gray(img)
plt.imshow(gray,cmap = plt.get_cmap('gray'))
plt.axis('on')
plt.show()
通过PIL灰度化
from PIL import Image
img = Image.open('test.jpg')
img.show() # 显示原图
L = img.convert('L') # 灰度化
L.show() # 显示灰度图
L = img.convert('1') # 二值化
L.show() # 二值化图
扩展:将某路径下的所有彩色图片灰度化:
from PIL import Image
import os
def get_path(path):
return [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]
pth = get_path('./')
print(pth)
for img in pth:
outfile = os.path.splitext(img)[0] + '.jpg'
print(outfile)
if './gray'+outfile.split('./')[1] not in pth and 'gray' not in outfile:
#if 'gray' not in outfile:
#print('1'+img)
try:
img = Image.open(img).convert('L')
#print('img',img)
#img.show()
im = 'gray' + outfile.split('./')[1]
img.save(im)
except IOError:
print('can not convert',img)
通过opencv灰度化
import cv2
from matpplotlib import pyplot as plt
im = cv2.imread('test.jpg')
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
plt.axis('off')
plt.imshow(im,'gray') # = plt.imshow(gray,cmap='gray') or plt.imshow(gray, cmap=plt.get_cmap('gray'))
plt.show()
在一些编程社区上经常看到:cv2.imshow(gray,'gray')
这样的代码,但是查阅了Python opencv官网却没发现这样的格式。并且本人在调用opencv的时候调用了cv2.imshow('img',img)
,然后就出现了进程无反应的状况,目前原因不详
问题解决:针对上述不显示图片并且进程卡死的问题,给出下列的解决方案:
import cv2
im = cv2.imread('test1.jpg') # cv2.imread('test1.jpg',0)直接输出灰度图
gray = cv2.cvtColor(im,cv2.COLOR_RGB2GRAY)
cv2.nameWindow('gray',0)
cv2.startWindowThread()
cv2.imshow('gray',gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
bug解决请参考:cv2.destoryAllWindows()无效的解决方法
详情可以查看opencv官方文档:https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_gui/py_image_display/py_image_display.html
二值化
opencv
固定阈值二值化
用到的函数:cv2.threshold(src, thresh, maxval, type[, dst])
,返回值为retval、dst
参数说明:
- src:输入图像
- thresh:阈值
- maxval:输出图像最大值
- type:阈值类型
- dst:目标图像
retval, im = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY)
plt.axis('off')
plt.title('二值化')
plt.imshow()
算法平均法的自适应二值化和高斯加权均值自适应二值化
用到的函数:`cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])`,返回值为`dst`
参数说明:
- src:输入图像
- maxval:输出图像的最大值
- adaptiveMethod:设置为
cv2.ADAPTIVE_THRESH_MEAN_C
表示使用算术平均值法,设置为cv2.ADAPTIVE_THRESH_GAUSSIAN_C
表示使用高斯权重均值法 - thresholdType:阈值类型
- blockSize:b的值
- C:从均值中减去的常数,用于得到阈值
- dst:目标图像
这里,我们将b设为5,C设为10
im = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_MEAN_C,cv2.THRESH_BINARY,5,10)
plt.axis('off')
plt.title('Adaptive Thresholding')
plt.imshow(im, cmap='gray')
plt.show()
绘制直方图
通过matplotlib库绘制灰度直方图
灰度图可以使用hist
函数绘制,这个函数第一个参数只能接受一位数组作为输入,所以第一个参数需要通过flatten
将任意数组按照行优先准则转换为一维数组;第二个参数则是规定小区间的数目。
from PIL import Image
from pylab import *
# 图片转换为数组并灰度化
img = array(Image.open('test.jpg').convert('L'))
# 直方图图像
hist(img.flatten(),128)
show()
或者这样:
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
im = np.array(Image.open('test.jpg').convert('L'))
plt.figure('gray')
plt.title('gray')
arr = im.flatten()
n,bins,patches = plt.hist(arr, bins=256, density=1, facecolor='blue', alpha=0.7)
plt.show()
hist
的参数说明:
- arr: 需要计算直方图的一维数组
- bins:直方图柱数,可选,默认为10
- density/normed:是否将得到的直方图向量归一化,默认为0
- facecolor:直方图颜色
- alpha:透明度
facecolor和edgecolor可以分别简写为fc
和ec
更多函数说明参考官方库:https://matplotlib.org/api/_as_gen/matplotlib.pyplot.hist.html
如果需要显示彩色图的直方图:
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
im = Image.open('test.jpg')
r,g,b = im.split()
# 也可以r = im[:,:,0], g = im[::,1], b = im[:,:,2]
plt.figure('Origin')
plt.title('Origin')
arr = np.array(r).flatten()
plt.hist(arr, bins=256, density=1, facecolor='r', edgecolor='r', hold=1)
arr = np.array(g).flatten()
plt.hist(arr, bins=256, density=1, facecolor='g', edgecolor='g', hold=1)
arr = np.array(b).flatten()
plt.hist(arr, bins=256, density=1, facecolor='b', edgecolor='b', hold=1)
plt.show()
形态学
膨胀和腐蚀
和MATLAB一样,Python opencv的膨胀腐蚀函数分别是dilate
和erode
简单地先通过OTSU二值化再进行腐蚀膨胀:
#coding=utf-8
import cv2
from matplotlib import pyplot as plt
import numpy as np
while(1):
im = cv2.imread('zui.jpg',0)
ret,th = cv2.threshold(im, 0, 255, cv2.THRESH_OTSU)
#plt.imshow(th,'otsu')
kernel = np.ones((3,3),np.uint8)
im1 = cv2.erode(th,kernel,iterations=7)
im2 = cv2.dilate(im1,kernel,iterations=1)
cv2.imshow('dilation',im2)
if cv2.waitKey(0):
break
cv2.destroyAllWindows()
开运算和闭运算:
import cv2
import numpy as np
while(1):
im = cv2.imread('test.jpg',0)
kernel = np.ones((3,3),np.uint8)
# or cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
open = cv2.morphologyEx(im, cv2.MORPH_OPEN, kernel)
# 如果是闭运算就是cv2.MORPH_CLOSE
cv2.imshow('Gray',im)
cv2.imshow('opening',open)
if cv2.waitKey(0):
break
cv2.destroyAllWindows()
更多有关Python opencv形态学的内容可以看:OpenCV-Python Tuorials Morphological Transformations
边沿检测:
#coding=utf-8
import cv2
import numpy as np
im = cv2.imread('zui.jpg')
im = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
dilation = cv2.dilate(im,kernel)
erodetion = cv2.erode(im, kernel)
edge = cv2.absdiff(dilation, erodetion) #两幅图相减得到边缘
ret,edge = cv2.threshold(edge, 50, 100, cv2.THRESH_BINARY) #二值化后观察更清晰
edge = cv2.bitwise_not(edge) #颜色反转
cv2.imshow('Origin',im)
cv2.imshow('Edge',edge)
if cv2.waitKey(0):
cv2.destroyAllWindows()
角点检测:
基本原理:
建立一个窗口区域,该窗口向各个方向进行平移,如果在没有遇到边角的情况下,窗口像素不会发送变化;如果窗口在偏移过程压过一条直线,并且沿着这条直线的方向进行平移,窗口像素值也不会变化;假如遇到了拐角,窗口偏移后任意方向都会有像素改变,即判断为角点
基本方法:cv2.cornerHarris()
和cv2.cornerSubPix()
cornerHarris
参数说明:
- img:输入图像,数据类型要是
float32
- blockSize:角点检测中的邻域值
- ksize:使用
Sobel
函数求偏导的窗口大小 - k:角点检测参数,取值为0.04到0.06
import cv2
import numpy as np
filename = 'test.jpg'
im = cv2.imread(filename)
gray = cv2.cvtColor(im, cv2.COLOR_RGB2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2,3,0.04)
dst = cv2.dilate(dst,None) #膨胀处理
im[dst > 0.01*dst.max()] = [0,0,255]
cv2.imshow('dst',im)
if cv2.waitKey(0):
cv2.destroyAllWindows()
亚像素级精确度的角点:
基本方法是cornerSubPix
,首先需要先找到Harris角点,然后找到某个角点的所有角点坐标值的重心,传入cornerSubPix
(因为一个角点上可能有一堆角点,所以要取重心)。我们用红色表示Harris角点,绿色表示修正后的角点。通过迭代运算到一定次数停止:
#coding=utf-8
import cv2
import numpy as np
filename = 'zui.jpg'
img = cv2.imread(filename)
gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
# 找角点
gray = np.float32(gray)
dst = cv2.cornerHarris(gray,2,3,0.04)
dst = cv2.dilate(dst,None)
ret,dst = cv2.threshold(dst,0.01*dst.max(),255,0)
dst = np.uint8(dst)
# 找重心
ret,labels,stats,centroids = cv2.connectedComponentsWithStats(dst)
# 定义迭代次数
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)
corners = cv2.cornerSubPix(gray,np.float32(centroids),(5,5),(-1,-1),criteria) # 返回角点
res = np.hstack((centroids,corners))
res = np.int0(res)
img[res[:,1],res[:,0]] = [0,0,255]
img[res[:,3],res[:,2]] = [0,255,0]
cv2.imshow('img',img)
if cv2.waitKey(0):
cv2.destroyAllWindows()
#coding=utf-8
# 代码来自:https://zhuanlan.zhihu.com/p/36801693
import cv2
import numpy as np
# 读取名称为 p14.png的图片
img = cv2.imread("p14.png",1)
img_org = cv2.imread("p14.png",1)
# 转换为黑白图像
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# 转换为32为浮点数
gray = np.float32(gray)
# Harris角点操作
processed = cv2.cornerHarris(gray,3,3,0.05)
# 把角点颜色变为绿色
img[processed>0.03*processed.max()] = [0,255,0]
# 显示原图和处理后的图像
cv2.imshow("org",img_org)
cv2.imshow("processed",img)
cv2.waitKey(0)
参考:
- matlab直方图均衡化详解及编程实现
- python图像直方图与直方图均衡化
- python 读取、保存、二值化、灰度化图片+opencv处理图片的方法
- python opencv入门 形态学转换(13)
- Python opencv英文文档
- Python opencv官方文档汉化,看云提供
- OpenCV-Python Tuorials Morphological Transformations
- 阈值化分割(二)OTSU法-附Python实现
- Morphological Transformations OpenCV Python Tutorial
- python opencv角点检测
- python opencv入门 Harris角点检测(31)
- python opencv入门 FAST角点检测算法(35)
- python opencv图像和视频分析
- OpenCV-Python教程(9、使用霍夫变换检测直线)
- OpenCV-Python 霍夫直线检测-HoughLinesP函数参数
- 学习OpenCV-Python——检测
- Python下opencv使用笔记(三)(图像的几何变换)
- Python下opencv使用笔记(四)(图像的阈值处理)