Python处理图片

1. 有两种相关处理图片的方法:Python-opencv和PIL(Image)

1.1 Python-opencv
1.1.1 图像读入
  • 第一种方法:使用cv2.cv的LoadImageShowImageSaveImage函数
import cv2.cv as cv

# 读图片
image=cv.LoadImage('img/image.png', cv.CV_LOAD_IMAGE_COLOR)#Load the image
#Or just: image=cv.LoadImage('img/image.png')

cv.NamedWindow('a_window', cv.CV_WINDOW_AUTOSIZE) #Facultative
cv.ShowImage('a_window', image) #Show the image

# 写图片
cv.SaveImage("thumb.png", thumb)
cv.WaitKey(0) #Wait for user input and quit
  • 第二种方法:使用cv2的imreadimwriteimshow函数
import numpy as np
import cv2

img = cv2.imread('messi5.jpg',0)
cv2.imshow('image',img)
k = cv2.waitKey(0)
if k == 27:         # wait for ESC key to exit
   cv2.destroyAllWindows()
elif k == ord('s'): # wait for 's' key to save and exit
   cv2.imwrite('messigray.png',img)
   cv2.destroyAllWindows()

为了加快处理速度,在图像处理算法中,往往首先需要把彩色图像转换为灰度图像。

1.1.2 进行灰度处理

灰度数字图像是每个像素只有一个采样颜色的图像,这类图像通常显示为从最暗黑色到最亮的白色的灰度。

灰度图像与黑白图像不同,在计算机图像领域中黑白图像只有黑白两种颜色,灰度图像在黑色与白色之间还有许多级的颜色深度。

在RGB模型中,如果R=G=B时,则彩色表示一种灰度颜色,其中R=G=B的值叫灰度值。

图像灰度化的算法主要有以下4种:

1)分量法:将彩色图像中的三分量的亮度作为三个灰度图像的灰度值,可根据应用需要选取一种灰度图像。

2)最大值法:使转化后的R,G,B得值等于转化前3个值中最大的一个,即:R=G=B=max(R,G,B)。这种方法转换的灰度图亮度很高。

 3)平均值法:是转化后R,G,B的值为转化前R,G,B的平均值。即:R=G=B=(R+G+B)/3。这种方法产生的灰度图像比较柔和。

 4)加权平均值法:按照一定权值,对R,G,B的值加权平均,即:![这里写图片描述](https://img-blog.csdn.net/20180106195145267?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMzk1MDc0NDU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)分别为R,G,B的权值,取不同的值形成不同的灰度图像。由于人眼对绿色最为敏感,红色次之,对蓝色的敏感性最低,因此使将得到较易识别的灰度图像。一般时,得到的灰度图像效果最好。 

Python-opencv代码实现灰度处理:

#第一种方法(分量法)
#导入opencv库
import cv2.cv as cv
#打开图片
image = cv.LoadImage('mao.jpg')
#函数cv.CreateImage()创建图像首地址,并分配存储空间
b = cv.CreateImage(cv.GetSize(image), image.depth, 1)
g = cv.CloneImage(b)
r = cv.CloneImage(b)
cv.Split(image, b, g, r, None)
cv.ShowImage('a_window', r)
    
cv.WaitKey(0)
#第二种方法(最大值法)
image = cv.LoadImage('mao.jpg')
new = cv.CreateImage(cv.GetSize(image), image.depth, 1)
for i in range(image.height):
    for j in range(image.width):
        new[i,j] = max(image[i,j][0], image[i,j][1], image[i,j][2])
cv.ShowImage('a_window', new)
cv.WaitKey(0)
#第三种方法(平均值法)
image = cv.LoadImage('mao.jpg')
new = cv.CreateImage(cv.GetSize(image), image.depth, 1)
for i in range(image.height):
    for j in range(image.width):
        new[i,j] = (image[i,j][0] + image[i,j][1] + image[i,j][2])/3
cv.ShowImage('a_window', new)
cv.WaitKey(0)

#第四种方法(加权平均法)
image = cv.LoadImage('mao.jpg')
new = cv.CreateImage(cv.GetSize(image), image.depth, 1)
for i in range(image.height):
    for j in range(image.width):
        new[i,j] = 0.3 * image[i,j][0] + 0.59 * image[i,j][1] +  0.11 * image[i,j][2]
cv.ShowImage('a_window', new)
cv.WaitKey(0)
1.1.3 二值化处理

图像二值化就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果。

将256个亮度等级的灰度图像通过适当的阈值选取而获得仍然可以反映图像整体和局部特征的二值化图像。

图像的二值化有利于图像的进一步处理,使图像变得简单,而且数据量减小,能凸显出感兴趣的目标的轮廓。

二值化处理:将一个像素点的值突出为0,255,使得图片呈现黑白两种颜色。在灰度图像中像素值在0~255,二值化后图像中像素值为0或255。

在将图像二值化之前需要将其先灰度化, 然后才能进行二值化处理。

第一种方法:

import cv2.cv as cv
image = cv.LoadImage('mao.jpg')
 
new = cv.CreateImage(cv.GetSize(image), image.depth, 1)
for i in range(image.height):
    for j in range(image.width):
        new[i,j] = max(image[i,j][0], image[i,j][1], image[i,j][2])
 
cv.Threshold(new, new, 10, 255, cv.CV_THRESH_BINARY_INV)
cv.ShowImage('a_window', new)
cv.WaitKey(0)

第二种方法:

import cv2 #导入cv2包
path = 'd:\\testdata\\test\\test1.jpg'  #图片路径

#adaptive threshold
img=cv2.imread(path)
im_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)  #转换成灰度图
im_at_mean = cv2.adaptiveThreshold(im_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C , cv2.THRESH_BINARY, 5, 10) #使用自适应阈值进行二值化处理,其他二值化方法可查询API使用

cv2.imshow('image', im_at_mean)
cv2.show()

①cv2.cvtColor() 将输入图像转成灰度图
②adaptiveThreshold( src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst] )将输入图像进行自适应阈值的二值化处理。其中blockSize是用来计算阈值的区域大小,C是从平均值或加权平均值中减去得到的常量。


例子:

# -*- coding=GBK -*-
import cv2 as cv
import numpy as np
 
 
#图像二值化 0白色 1黑色
#全局阈值
def threshold_image(image):
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
    cv.imshow("原来", gray)
 
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)#大律法,全局自适应阈值 参数0可改为任意数字但不起作用
    print("阈值:%s" % ret)
    cv.imshow("OTSU", binary)
 
    ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY | cv.THRESH_TRIANGLE)#TRIANGLE法,,全局自适应阈值, 参数0可改为任意数字但不起作用,适用于单个波峰
    print("阈值:%s" % ret)
    cv.imshow("TRIANGLE", binary)
 
    ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_BINARY)# 自定义阈值为150,大于150的是白色 小于的是黑色
    print("阈值:%s" % ret)
    cv.imshow("自定义", binary)
 
    ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_BINARY_INV)# 自定义阈值为150,大于150的是黑色 小于的是白色
    print("阈值:%s" % ret)
    cv.imshow("自定义反色", binary)
 
    ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_TRUNC)# 截断 大于150的是改为150  小于150的保留
    print("阈值:%s" % ret)
    cv.imshow("截断1", binary)
 
    ret, binary = cv.threshold(gray, 150, 255, cv.THRESH_TOZERO)# 截断 小于150的是改为150  大于150的保留
    print("阈值:%s" % ret)
    cv.imshow("截断2", binary)
 
src = cv.imread("C://1.jpg")
threshold_image(src)
cv.waitKey(0)
cv.destroyAllWindows()

在这里插入图片描述

1.1.4 降噪

在处理图像识别问题中,处理图片噪点,像周围的一些细节很丰富,小的黑白点交错。但是,这些“细节”是我们在真正使用时,所不需要的,会影响我们对主要特征的提取,因此我们一般都要进行降噪处理。

(1)将每个像素替换为该像素周围像素的均值。这样就可以平滑并替代那些强度变化明显的区域。

result = cv2.blur(image,(5,5))
 
#上为均值模糊去噪方法。周围的都为均值
#又称为低通滤波
 
gaussianResult = cv2.GaussianBlur(img,(5,5),1.5)
 
#上为高斯模糊去噪方法。在某些情况下,需要对一个像素的周围的像素给予更多的重视。因此,可通过分配权重来重新计算这些周围点的值。
#(5,5)不可以随意指定,只能指定1,3,5,7.....等数字

(2滤波与高斯滤波的不同之处在于:低通滤波中,滤波器中每个像素的权重是相同的,即滤波器是线性的。而高斯滤波器中像素的权重与其距中心像素的距离成比例。

还有一种去噪方法为中值滤波器。(主要用来处理图像中的椒盐现象)

result = cv2.medianBlur(image,5)
1.1.5 剪裁

使用OpenCV的findContours获取轮廓并切割(python)

(1)获取轮廓

OpenCV2获取轮廓主要是用cv2.findContours

import numpy as np
import cv2

im = cv2.imread('test.jpg')
imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
#查找检测物体的轮廓
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

(2)画出轮廓

为了看到自己画了哪些轮廓,可以使用 cv2.boundingRect()函数获取轮廓的范围,即左上角原点,以及他的高和宽。然后用cv2.rectangle()方法画出矩形轮廓

for i in range(0,len(contours)):  
    # 画出矩形(图片,矩形左上角,矩形右下角,线框的颜色,线宽)
    x, y, w, h = cv2.boundingRect(contours[i])   
    cv2.rectangle(image, (x,y), (x+w,y+h), (153,153,0), 5) 

(3)切割轮廓

轮廓的切割主要是通过数组切片实现的,不过这里有一个小技巧:就是图片切割的w,h是宽和高,而数组讲的是行(row)和列(column) 所以,在切割图片时,数组的高和宽是反过来写的

  newimage=image[y+2:y+h-2,x+2:x+w-2] # 先用y确定高,再用x确定宽
            nrootdir=("E:/cut_image/")
            if not os.path.isdir(nrootdir):
                os.makedirs(nrootdir)
            cv2.imwrite( nrootdir+str(i)+".jpg",newimage) 
            print (i)
1.2 PIL Image图像处理库

利用 PIL 中的函数,我们可以从大多数图像格式的文件中读取数据,然后写入最常见的图像格式文件中。PIL 中最重要的模块为 Image。要读取一幅图像,可以使用:

from PIL import Image

pil_im = Image.open('empire.jpg')

图像的颜色转换可以使用 convert() 方法来实现。要读取一幅图像,并将其转换成灰度图像,只需要加上 convert('L'),如下所示:

pil_im = Image.open('empire.jpg').convert('L')

图片调整尺寸和旋转:

要调整一幅图像的尺寸,我们可以调用 resize() 方法。该方法的参数是一个元组,用来指定新图像的大小:

out = pil_im.resize((128,128))

要旋转一幅图像,可以使用逆时针方式表示旋转角度,然后调用 rotate() 方法:

out = pil_im.rotate(45)

图片进行二值化处理:

'L’表示灰度,'1’表示二值图模式。

转换过程的关键在于设计映射表,如果只是需要一个简单的箝位值,可以将table中高于或低于箝位值的元素分别设为1与0。当然,由于这里的table并没有什么特殊要求,所以可以通过对元素的特殊设定实现(0, 255)范围内,任意需要的一对一映射关系。

import Image

# load a color image
im = Image.open('fun.jpg')

# convert to grey level image
Lim = im.convert('L')
Lim.save('fun_Level.jpg')

# setup a converting table with constant threshold
threshold = 80
table = []
for i in range(256):
    if i < threshold:
        table.append(0)
    else:
        table.append(1)

# convert to binary image by the table
bim = Lim.point(table, '1')

bim.save('fun_binary.jpg')

图片如下图所示:

“fun.jpg”:
在这里插入图片描述

“fun_Level.jpg”:
在这里插入图片描述

“fun_binary.jpg”:
在这里插入图片描述

Image库显示图片:

file_name='/home/cris/AI/MNIST/image/finaly.png'#导入自己的图片地址
im = Image.open(file_name).convert('L')
 #将图片进行剪裁成28*28像素大小
img = im.resize((28, 28), Image.ANTIALIAS).filter(ImageFilter.SHARPEN)
#显示图片
img.show()

Image库剪裁图片:

rom PIL import Image

img = Image.open('1.jpg') # 打开当前路径图像

box1 = (14, 4, 53, 52) # 设置图像裁剪区域 (x左上,y左上,x右下,y右下)

image1 = img.crop(box1) # 图像裁剪

image1.save('image1.jpg') # 存储裁剪得到的图像
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值