图像灰度化并不是将单纯的图像变成灰色,而是将图片的BGR各通道以某种规律综合起来,使图片显示位灰色。
规律如下:
首先我们采用手动灰度化的方式:
其思想就是:
先创建一个跟原来长宽一样的空白图片,然后将原图片中图片各个像素按照下面公式填入图片中,实现灰度化。
import cv2
import numpy as np
from skimage.color import rgb2gray
from PIL import Image
import matplotlib.pyplot as plt
img = cv2.imread("lenna.png") #opencv读取图像
#img = plt.imread("lenna.png") #matlab读取图像
h,w = img.shape[:2] #读出图像的长宽
img_gray = np.zeros([h,w],img.dtype) #创建一个与当前图像相同长宽的单通道图片
for i in range(h):
for j in range(w):
m = img[i,j]
img_gray[i,j] = int(m[0]*0.11+m[1]*0.59+m[2]*0.3) #将CV读取的BGR转化为gray值给新图像
print(img_gray)
cv2.imshow('gray picture ',img_gray) #cv展示灰色图像
cv2.waitKey (0) #如果不写等待时间,图像会一闪而过
img = cv2.imread("lenna.png")
img_gray = rgb2gray(img)
cv2.imshow('gray picture ',img_gray)
cv2.waitKey (0)
img = cv2.imread("lenna.png")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#用opencv输出
cv2.imshow('gray picture ',img_gray)
cv2.waitKey (0)
#用plt输出:这里要注意,cmap为颜色图谱,默认为RGB(A)颜色空间,也可以指定,gray是灰度图,若cmap为其他会造成色差
plt.imshow(img_gray,cmap="gray")
plt.show()
所谓图像二值化,就是将图像中像素点的值取其中间值,若大于中间值,则将该像素点的值设为最大值,若小于中间值,则把该像素点设为最小值。使整个图片最后只存在两个值:最大值和最小值。
img = plt.imread("lenna.png")
img_gray = rgb2gray(img) #这里还是要先灰度化
rows, cols = img_gray.shape
for i in range(rows):
for j in range(cols):
if (img_gray[i, j] <= 0.5):
img_gray[i, j] = 0
else:
img_gray[i, j] = 1
plt.imshow(img_gray,cmap="gray")
plt.show()
img = plt.imread("lenna.png")
img_gray = rgb2gray(img)#这里还是要先灰度化
img_binary = np.where(img_gray >= 0.5, 1, 0)
plt.imshow(img_binary,cmap="gray")
plt.show()
img = cv2.imread("lenna.png")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#这里还是要先灰度化
cv2.threshold(img_gray,127,255,0,img_gray)
cv2.imshow('img_binary',img_gray)
cv2.waitKey(0)
import cv2
import numpy as np
from skimage.color import rgb2gray
from PIL import Image
import matplotlib.pyplot as plt
"""
手动实现图像灰度化
"""
img = cv2.imread("lenna.png") #opencv读取图像
#img = plt.imread("lenna.png") #matlab读取图像
h,w = img.shape[:2] #读出图像的长宽
img_gray = np.zeros([h,w],img.dtype) #创建一个与当前图像相同长宽的单通道图片
for i in range(h):
for j in range(w):
m = img[i,j]
img_gray[i,j] = int(m[0]*0.11+m[1]*0.59+m[2]*0.3) #将CV读取的BGR转化为gray值给新图像,注意:这个公式是内定的
print(img_gray)
cv2.imshow('gray picture ',img_gray) #cv展示灰色图像
cv2.waitKey (0) #如果不写等待时间,图像会一闪而过
"""
skimage实现图像灰度化
"""
img = cv2.imread("lenna.png")
img_gray = rgb2gray(img)
cv2.imshow('gray picture ',img_gray)
cv2.waitKey (0)
"""
opencv实现图像灰度化
"""
img = cv2.imread("lenna.png")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#用opencv输出
cv2.imshow('gray picture ',img_gray)
cv2.waitKey (0)
plt.imshow(img_gray,cmap="gray")
plt.show()
"""
手动图像二值化
"""
img = plt.imread("lenna.png")
img_gray = rgb2gray(img)
rows, cols = img_gray.shape
for i in range(rows):
for j in range(cols):
if (img_gray[i, j] <= 0.5):
img_gray[i, j] = 0
else:
img_gray[i, j] = 1
plt.imshow(img_gray,cmap="gray")
plt.show()
"""
numpy实现图像二值化
"""
img = plt.imread("lenna.png")
img_gray = rgb2gray(img)
img_binary = np.where(img_gray >= 0.5, 1, 0)
plt.imshow(img_binary,cmap="gray")
plt.show()
"""
opencv实现图像二值化
"""
img = cv2.imread("lenna.png")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.threshold(img_gray,127,255,0,img_gray)
cv2.imshow('img_binary',img_gray)
cv2.waitKey(0)
在plt读取图像之后,图像的每一个像素值都在[0,1]之间,在之后的cv2读取的图像,每一个像素值在[0,255]之间,所以在二值化时,plt是阈值为0.5,像素值分成0或1,而cv2中阈值是127,像素值分为0或255。
因为 opencv 的接口使用BGR模式,而 matplotlib.pyplot 接口使用的是RGB模式
解决方法是:
在cv输入图像后把通道顺序变换一下,就在cv2.imread输入后面添加
b, g, r = cv2.split(img)
img = cv2.merge([r, g, b])
用plt输出中cmap为颜色图谱,默认为RGB(A)颜色空间,也可以指定,gray是灰度图,若cmap为其他会造成色差
无论谁cv输出还是plt输出的最后的结尾都需要加上cv.waitkey(0)
或者plt.show()
不然输出图像转瞬即逝,很快就消失了,不能长时间停留。
PLT:
#输入
img = plt.imread("lenna.png")
#输出
plt.imshow(img,cmap="gray")
plt.show()
CV:
#输入
img = cv2.imread("lenna.png")
#输出
cv2.imshow('img',img_gray)
cv2.waitKey(0)
这里注意:cv2的输出必须有标题,不然会报错。