计算机视觉:图像基本操作实验

计算机视觉:图像基本操作实验

1.实验内容:

1.分别使用PIL库和OpenCV库读取图像并实现可视化,对比 OpenCV读取和PIL读取的差异;

实现方法:
def Showimg():
    img1=cv2.imread(ImagePath)
    img2=Image.open(ImagePath)
    print('opencv_type',type(img1))#输出类型对比差别
    print("pil_type",type(img2))
    print('opencv_shape',img1.shape)#输出读入顺序
    print('pil_size',img2.size)
    # img1.show()
    cv2.imshow('opencvimg',img1)
    cv2.waitKey(0)
    img2.show()
    # cv2.imshow('pilimg',img2)

实验结果:

Opencv读取图像可视化

image-20230322200758078

PIL读取图像可视化

image-20230322200816891

读取差别验证:

image-20230322200940514

结果分析:

二者的图像读取格式不同,当图像格式为jpg时,PIL读入图像,类型为PIL.JpegImagePlugin.JpegImageFile;OpenCV读入图像,直接就是numpy.ndarray。

二者的宽高的读取顺序不同,PIL读入图像,顺序为:(宽,高)OpenCV读入图像,顺序为:(高,宽,通道数)

除此外二者的区别还有读取的通道顺序不同,PIL读入为R、G、B;OpenCV读入为B、G、R

2.利用thumbnail()函数创建图像缩略图,利用resize()函数 处理图像,对比两者差别;

实现方法:
#利用thumbnail()函数创建图像缩略图,利用resize()函数处理图像,对比两者差别;
def ChangeSize():
    img1=Image.open(ImagePath)
    img2=Image.open(ImagePath)
    print('原尺寸',img1.size)
    img1.thumbnail((256,256))
    print('缩略图尺寸',img1.size)
    img1.show('thumbnail')
    img2=img2.resize((256,256))
    print('resize尺寸',img2.size)
    img2.show('resize')
    
实验结果:

左边为thumbnail处理图像,右边为resize处理图像

image-20230322201639923

处理前后图片大小对比:

image-20230322201850648

结果分析:

thumbnail ()之后的图片大小与预设的不一样,而 resize() 就不会这样

resize()函数会返回一个Image对象, thumbnail()函数返回None。

resize()中的size参数直接设定了resize之后图片的规格, 而thumbnail()中的size参数则是设定了图片大小的最大值. 所以经过resize()处理的图片可能会被拉伸, 而经过thumbnail()处理的图片不会被拉伸。

3.绘制图像的轮廓与直方图;

实现方法:
#绘制图像的轮廓与直方图
def ContourAndHist():
    img=array(Image.open(ImagePath).convert('L'))#读取转化灰度
    # cv2.imshow('grayimg',img)
    # cv2.waitKey(0)
    figure()
    gray()#不使用颜色信息
    contour(img,origin="image")
    axis=('equal')
    axis=('off')
    figure()
    hist(img.flatten(),128)
    show()

实验结果:

image-20230322202857235

结果分析:

绘制轮廓需要对每个坐标的像素值施加一个阈值,所以首先需要将图像灰度化。

直方图:用来表征该图像像素值得分布情况。用一定的小区间来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目。hist()函数:参数二:指定小区间的数目。参数一:只接受一维数组作为输入,因此在绘制图像直方图前,必须对图像进行压平处理。flatten()将任意数组按照行优先准则转换成一维数组。

4.实现图像的灰度变换、直方图均衡化;

实现方法:
#实现图像的灰度变换、直方图均衡化
def GraytrAndHisteq():
    img=array(Image.open(ImagePath).convert('L'))
    img1=255-img#反相处理
    img2=(100.0/255)*img+100#灰度值转化到100至200间
    img3=255.0*(img/255.0)**2#灰度值平方
    figure()
    gray()
    imshow(img)
    figure()
    gray()
    imshow(img1)
    figure()
    gray()
    imshow(img2)
    figure()
    gray()
    imshow(img3)
    # Image.fromarray(uint8(img)).show()
    # Image.fromarray(uint8(img1)).show()
    # Image.fromarray(uint8(img2)).show()
    # Image.fromarray(uint8(img3)).show()
    img0,cdf=histeq(img)
    figure()
    gray()
    imshow(img0)
    # Image.fromarray(uint8(img0)).show()
    figure()
    hist(img0.flatten(),128)
    show()

#直方图均衡化具体方法
def histeq(img,nbr_bins=256):#bin指定直方图条数
    imghist,bins = histogram(img.flatten(),nbr_bins,normed=True)#计算图像的直方图
    cdf=imghist.cumsum()
    cdf=255*cdf/cdf[-1]#归一化
    img2=interp(img.flatten(),bins[:-1],cdf)#使用cdf的线性插值计算新的像素值
    return img2.reshape(img.shape),cdf

实验结果:

从左到右依次为 :原图、反相处理、灰度值转化到100至200间、灰度值平方

image-20230322205458320

直方图均衡化后的灰度图以及灰度直方图:

image-20230322205730219

结果分析:

直方图均衡化后图像的对比度增强了,原先图像灰色区域的细节变得清晰

5.实现图像的不同高斯模糊、计算导数;

实现方法:

高斯模糊

#实现图像的不同高斯模糊
def GaussianBlur():
    #模糊灰度图
    grayimg=array(Image.open(ImagePath).convert('L'))
    for i in range(3):
        img0=filters.gaussian_filter(grayimg,5*i+5)
        Image.fromarray(uint8(img0)).show()
    
    #高斯模糊彩色图像
    img=array(Image.open(ImagePath))
    img1=zeros(img.shape)#创建一个列表用来存储彩色图像
    for i in range(3):
        for j in range(3):
            img1[:,:,j]=filters.gaussian_filter(img[:,:,j],5*i+5)
        img1=uint8(img1)
        img1=array(img1,'uint8')
        Image.fromarray(uint8(img1)).show()


计算导数:

#计算导数
def Derivative():
    img=array(Image.open(ImagePath).convert('L'))
    #Sobel滤波
    imgy=zeros(img.shape)
    filters.sobel(img,0,imgy)#导数方向选择,1为x方向,0为y方向
    Image.fromarray(uint8(imgy)).show()
    imgx=zeros(img.shape)
    filters.sobel(img,1,imgx)#导数方向选择,1为x方向,0为y方向
    Image.fromarray(uint8(imgx)).show()
    #gaussian滤波
    sigma=5
    imgy2=zeros(img.shape)
    filters.gaussian_filter(img,(sigma,sigma),(1,0),imgy2)#导数方向选择,1,0为y方向
    Image.fromarray(uint8(imgy2)).show()
    imgx2=zeros(img.shape)
    filters.gaussian_filter(img,(sigma,sigma),(0,1),imgx2)#导数方向选择,0,1为x方向
    Image.fromarray(uint8(imgx2)).show()


实验结果:

灰度图像的不同高斯模糊:σ=5,σ=10,σ=15

image-20230322210711007

彩色图像的不同高斯模糊:σ=5,σ=10,σ=15

image-20230322211150275

Sobel滤波求导数:Y方向、X方向

image-20230322211737498

高斯滤波求导数:Y方向、X方向、sigma=5

image-20230322212020944

高斯滤波求导数:Y方向、X方向、sigma=1

image-20230323220829112

结果分析:

sobel()函数的第二个参数表示选择x或者y方向导数,第三个参数保存输出的变量,在使用sobel两个导数图像中,正导数显示为亮的像素,负导数显示为暗的像素。灰色区域表示导数的值接近于零

使用Gaussian滤波求导的效果可视化较差,原因是由于sigma过大,当将sigma调小后,可视化效果变得较好。

6.形态学计数(计算圆形个数等)、去噪;

实现方法:

形态学计数

def ObjNum():
    #载入图像
    img=array(Image.open('./cell.png').convert('L'))
    #阙值化操作,保证图像是二值图像
    img=1*(img<128)
    labels,num= measurements.label(img)
    print('数量:',num)
    # print(type(labels))
    # Image.fromarray(uint8(img)).show()
    figure()
    gray()
    imshow(img)
    plt.title(num)
    # figure()
    # gray()
    # imshow(labels)
    show()

去噪

#ROF模型实现图像去噪
def Denoise():
    img=array(Image.open(ImagePath).convert('L'))
    figure()
    gray()
    imshow(img)
    U,T=denoise(img,img)
    figure()
    gray()
    imshow(U)
    figure()
    gray()
    imshow(T)
    show()



#去噪声具体方法  返回的U
def denoise(im,U_init,tolerance=0.1,tau=0.125,tv_weight=100):
    """使用A. Chambolle(2005)在公式(11)中的计算步骤实现Rudin-Osher-Fatemi(ROF)去噪模型
        输入:含有噪声的输入图像(灰度图像)、U的初始值、TV正则项权值、步长、停业条件
        输出:去噪和去除纹理后的图像、纹理残留"""
    m,n = im.shape  #噪声图像的大小
 
    #初始化
    U = U_init
    Px = im #对偶域的x分量
    Py = im #对偶域为y分量
    error = 1
 
    while(error>tolerance):
        Uold = U
 
        #原始变量的梯度
        GradUx = roll(U,-1,axis=1)-U    #变量U梯度的x分量
        GradUy = roll(U,-1,axis=0)-U    #变量U梯度的y分量
 
        #更新对偶变量
        PxNew = Px + (tau/tv_weight)*GradUx
        PyNew = Py + (tau/tv_weight)*GradUy
        NormNew = maximum(1,sqrt(PxNew**2+PyNew**2))
 
        Px = PxNew/NormNew  #更新x分量(对偶)
        Py = PyNew/NormNew  #更新y分量(对偶)
 
        #更新原始变量
        RxPx = roll(Px,1,axis=1)    #对x分量进行向右x轴平移
        RyPy = roll(Py,1,axis=0)    #对y分量进行向右y轴平移
 
        DivP = (Px-RxPx) + (Py-RyPy) #对偶域的散度
        U = im + tv_weight*DivP  #更新原始变量
 
        #更新误差
        error = linalg.norm(U - Uold)/sqrt(n*m)
 
    return U,im-U #去噪后的图像和纹理残余

实验结果:

终端或图片标题可以查看估计的图形数量:

image-20230322213718129

从左到右分别为原图的灰度图、去噪后图像、去噪后的纹理残余图像

image-20230322213934382

结果分析:

上述使用的计数方法的结果受图像的二值化效果影响较大,当二值化的阈值改变时,对计数结果影响很大。

2.实验实现总代码

import cv2
import numpy as np
from PIL import Image
import os
from pylab import *
from scipy.ndimage import filters
from scipy.ndimage import measurements,morphology



ImagePath='./testimg.jpg'

#分别使用PIL库和OpenCV库读取图像并实现可视化,对比OpenCV读取和PIL读取的差异;
def Showimg():
    img1=cv2.imread(ImagePath)
    img2=Image.open(ImagePath)
    print('opencv_type',type(img1))#输出类型对比差别
    print("pil_type",type(img2))
    print('opencv_shape',img1.shape)#输出读入顺序
    print('pil_size',img2.size)
    # img1.show()
    cv2.imshow('opencvimg',img1)
    cv2.waitKey(0)
    img2.show()
    # cv2.imshow('pilimg',img2)


#利用thumbnail()函数创建图像缩略图,利用resize()函数处理图像,对比两者差别;
def ChangeSize():
    img1=Image.open(ImagePath)
    img2=Image.open(ImagePath)
    print('原尺寸',img1.size)
    img1.thumbnail((256,256))
    print('缩略图尺寸',img1.size)
    img1.show('thumbnail')
    img2=img2.resize((256,256))
    print('resize尺寸',img2.size)
    img2.show('resize')
    

#绘制图像的轮廓与直方图
def ContourAndHist():
    img=array(Image.open(ImagePath).convert('L'))#读取转化灰度
    # cv2.imshow('grayimg',img)
    # cv2.waitKey(0)
    figure()
    gray()#不使用颜色信息
    contour(img,origin="image")
    axis=('equal')
    axis=('off')
    figure()
    hist(img.flatten(),128)
    show()


#实现图像的灰度变换、直方图均衡化
def GraytrAndHisteq():
    img=array(Image.open(ImagePath).convert('L'))
    img1=255-img#反相处理
    img2=(100.0/255)*img+100#灰度值转化到100至200间
    img3=255.0*(img/255.0)**2#灰度值平方
    figure()
    gray()
    imshow(img)
    figure()
    gray()
    imshow(img1)
    figure()
    gray()
    imshow(img2)
    figure()
    gray()
    imshow(img3)
    # Image.fromarray(uint8(img)).show()
    # Image.fromarray(uint8(img1)).show()
    # Image.fromarray(uint8(img2)).show()
    # Image.fromarray(uint8(img3)).show()
    img0,cdf=histeq(img)
    figure()
    gray()
    imshow(img0)
    # Image.fromarray(uint8(img0)).show()
    figure()
    hist(img0.flatten(),128)
    show()

#直方图均衡化具体方法
def histeq(img,nbr_bins=256):#bin指定直方图条数
    imghist,bins = histogram(img.flatten(),nbr_bins,normed=True)#计算图像的直方图
    cdf=imghist.cumsum()
    cdf=255*cdf/cdf[-1]#归一化
    img2=interp(img.flatten(),bins[:-1],cdf)#使用cdf的线性插值计算新的像素值
    return img2.reshape(img.shape),cdf


#实现图像的不同高斯模糊
def GaussianBlur():
    #模糊灰度图
    grayimg=array(Image.open(ImagePath).convert('L'))
    for i in range(3):
        img0=filters.gaussian_filter(grayimg,5*i+5)
        Image.fromarray(uint8(img0)).show()
    
    #高斯模糊彩色图像
    img=array(Image.open(ImagePath))
    img1=zeros(img.shape)#创建一个列表用来存储彩色图像
    for i in range(3):
        for j in range(3):
            img1[:,:,j]=filters.gaussian_filter(img[:,:,j],5*i+5)
        img1=uint8(img1)
        img1=array(img1,'uint8')
        Image.fromarray(uint8(img1)).show()



#计算导数
def Derivative():
    img=array(Image.open(ImagePath).convert('L'))
    #Sobel滤波
    imgy=zeros(img.shape)
    filters.sobel(img,0,imgy)#导数方向选择,1为x方向,0为y方向
    Image.fromarray(uint8(imgy)).show()
    imgx=zeros(img.shape)
    filters.sobel(img,1,imgx)#导数方向选择,1为x方向,0为y方向
    Image.fromarray(uint8(imgx)).show()
    #gaussian滤波
    sigma=5
    imgy2=zeros(img.shape)
    filters.gaussian_filter(img,(sigma,sigma),(1,0),imgy2)#导数方向选择,1,0为y方向
    Image.fromarray(uint8(imgy2)).show()
    imgx2=zeros(img.shape)
    filters.gaussian_filter(img,(sigma,sigma),(0,1),imgx2)#导数方向选择,0,1为x方向
    Image.fromarray(uint8(imgx2)).show()


def ObjNum():
    #载入图像
    img=array(Image.open('./cell.png').convert('L'))
    #阙值化操作,保证图像是二值图像
    img=1*(img<128)
    labels,num= measurements.label(img)
    print('数量:',num)
    print(type(labels))
    # Image.fromarray(uint8(img)).show()
    figure()
    gray()
    imshow(img)
    # figure()
    # gray()
    # imshow(labels)
    show()

#ROF模型实现图像去噪
def Denoise():
    img=array(Image.open(ImagePath).convert('L'))
    figure()
    gray()
    imshow(img)
    U,T=denoise(img,img)
    figure()
    gray()
    imshow(U)
    figure()
    gray()
    imshow(T)
    show()



#去噪声具体方法  返回的U
def denoise(im,U_init,tolerance=0.1,tau=0.125,tv_weight=100):
    """使用A. Chambolle(2005)在公式(11)中的计算步骤实现Rudin-Osher-Fatemi(ROF)去噪模型
        输入:含有噪声的输入图像(灰度图像)、U的初始值、TV正则项权值、步长、停业条件
        输出:去噪和去除纹理后的图像、纹理残留"""
    m,n = im.shape  #噪声图像的大小
 
    #初始化
    U = U_init
    Px = im #对偶域的x分量
    Py = im #对偶域为y分量
    error = 1
 
    while(error>tolerance):
        Uold = U
 
        #原始变量的梯度
        GradUx = roll(U,-1,axis=1)-U    #变量U梯度的x分量
        GradUy = roll(U,-1,axis=0)-U    #变量U梯度的y分量
 
        #更新对偶变量
        PxNew = Px + (tau/tv_weight)*GradUx
        PyNew = Py + (tau/tv_weight)*GradUy
        NormNew = maximum(1,sqrt(PxNew**2+PyNew**2))
 
        Px = PxNew/NormNew  #更新x分量(对偶)
        Py = PyNew/NormNew  #更新y分量(对偶)
 
        #更新原始变量
        RxPx = roll(Px,1,axis=1)    #对x分量进行向右x轴平移
        RyPy = roll(Py,1,axis=0)    #对y分量进行向右y轴平移
 
        DivP = (Px-RxPx) + (Py-RyPy) #对偶域的散度
        U = im + tv_weight*DivP  #更新原始变量
 
        #更新误差
        error = linalg.norm(U - Uold)/sqrt(n*m)
 
    return U,im-U #去噪后的图像和纹理残余




if __name__ == '__main__':
    # Showimg()
    # ChangeSize()
    # ContourAndHist()
    # GraytrAndHisteq()
    # GaussianBlur()
    # Derivative()
    # ObjNum()
    # Denoise()

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值