python机器视觉(1)——图像处理

点运算

       点运算是最简单的一类图像处理方法,它不依赖它邻域像素。图像可分为灰度图、RGB图和HSV图,目前本篇主要以灰度图和RGB图为主,介绍一些经典例子。图像灰度、RGB互转的原理,会后面专门开一个文章介绍。

        点运算最经典的两个算子是:g(x)=af(x)+b,其中a是增益参数,b是偏差参数,他们分别控制图像的对比度和亮度;对于两幅输入图像的处理,有g(x)=(1-\alpha )f_{0}(x)+\alpha f_{1}(x),其中\alpha从0到1变化,可以实现图像的渐变切换、甚至是合成与抠图,这里随手写了一个渐变代码。

import cv2
import numpy as np
 
img = cv2.imread('image.jpg')
img1 = cv2.imread('image1.jpg')
img = cv2.resize(img,(500,500))
img1 = cv2.resize(img1,(500,500))
newImg = np.zeros(img.shape,np.uint8)
for i in np.arange(0,1,0.1):
    newImg = (1-i)*img + i*img1
    newImg = newImg.astype(np.uint8)
    cv2.imshow('newImg',newImg)
    cv2.waitKey(100)

负片

       负片(Negative Film)是经曝光和显影加工后得到的影像,其明暗与被摄体相反,其色彩则为被摄体的补色,一般来说,可以用像素值最大值减去当前值,即{y}'=255-y,代码如下:

import cv2
import numpy as np

img = cv2.imread('image.png')
img = 255-img
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

直接用RGB图片,处理后结果为:

伽马校正

伽马校正是一个很常见的非线性算子,它可以去除输入辐射量和量化的像素值之间的非线性映射,一般用g(x)=[f(x)]^{1/\gamma },其中\gamma取2.2合适。

import cv2
import numpy as np
 
img = cv2.imread('image.png')
newImg = np.zeros(img.shape,np.uint8)
gamma = 2.2
newImg = pow(img,1/gamma)
newImg = newImg.astype(np.uint8)
cv2.imshow('newImg',newImg)
cv2.waitKey(0)
cv2.destroyAllWindows()

直方图均衡化、规定化

        直方图是检测图像亮度值的集合,可以从中读取到最大小值、平均亮度值等,为了更好显示直方图,我们一般会将直方图归一化,即用概率p_{i}=h(i)/N表示像素值i的数量h(i)出现的概率。

        为了将直方图的对比度均匀处理,采用概率密度函数c(I)=\frac{1}{N}\sum_{i=0}^{I} h(i)绘制累积直方图,然后利用映射函数f(I)=\alpha c(I)+(1-\alpha )I求出新图像。

        直方图规定化希望将原图像和目标图像的分布相匹配,主要利用累积直方图。原图像素值对应的累积直方图数值=目标图累积直方图数值对应的像素值,一一赋值即可,以下为一个灰度图的直方图规定化:

import cv2
import numpy as np
import matplotlib.pyplot as plt
import copy
 
def hist(img):#直方图
    hist_number = np.zeros(256,np.float64)
    for i in range(img.shape[0]):   #遍历像素点
        for j in range(img.shape[1]):
            k = img[i][j]           #获取灰度值k
            hist_number[k] += 1     #在hist_number数组里计数,对应k级灰度值的数量
    hist_number = hist_number/(img.shape[0]*img.shape[1])   #归一化
    return hist_number              #返回各灰度值占比的数组
 
def acc_hist(acc_hist_number):      #累积直方图
    for k in range(1,256):          #注意累加应该从第二个元素开始
        acc_hist_number[k] += acc_hist_number[k-1]    #累加
    return acc_hist_number          #返回各累积灰度值占比的数组
 
def plt_hist(image,array_hist,array_acc_hist,title):  #绘制直方图和累积直方图
    plt.subplot(211)
    plt.title(title)
    plt.bar(range(256),array_hist,width=1)
    plt.subplot(212)
    plt.plot(range(256),array_acc_hist)
    plt.show()

if __name__ == '__main__':

    #读取原图片和匹配目标图片
    originImg = cv2.imread('image.png',0)
    targetImg = cv2.imread('image1.png',0)

    #直方图、累积直方图
    originImg_hist_number = hist(originImg)
    originImg_acc_hist_number = acc_hist(copy.copy(originImg_hist_number))  #不能直接在原数组上操作,故用copy函数,将原数组复制分离
    targetImg_hist_number = hist(targetImg)
    targetImg_acc_hist_number = acc_hist(copy.copy(targetImg_hist_number))
    
    # 将两张图片的灰度级进行匹配
    newImg = np.zeros(originImg.shape, np.uint8)   
    for j in range(256):
        temp = abs(targetImg_acc_hist_number - originImg_acc_hist_number[j])    #如果两数据相近,则相减后应趋向0
        # 找出最接近的灰度级并进行匹配
        temp = temp.tolist()
        newImg[originImg[:, :] == j] = temp.index(min(temp))
    
    newImg_hist_number = hist(newImg)
    newImg_acc_hist_number = acc_hist(copy.copy(newImg_hist_number))

    #绘制
    plt.figure(1)
    plt_hist(originImg,originImg_hist_number,originImg_acc_hist_number,'originImg')
    plt.figure(2)
    plt_hist(targetImg,targetImg_hist_number,targetImg_acc_hist_number,'targetImg')
    plt.figure(3)
    plt_hist(newImg_hist_number,newImg_acc_hist_number,'newImg')

    #保存图片
    cv2.imwrite('newImg_path.png', newImg)

对比度拉伸

       某些图像的直方图会出现较窄而高的情况,分布不均匀,对比度不高,除了直方图均衡化外,还可以将窄而高的区间,线性映射到整个像素大小空间,公式为:

I(x,y)=\frac{I(x,y)-I_{min}}{I_{max}-I_{min}}(MAX-MIN)+MIN

       其中Imin,Imax是原始图像的最小灰度值和最大灰度值,MIN和MAX是要拉伸到的灰度空间的灰度最小值和最大值。

import cv2
import numpy as np
img = cv2.imread('image1.png')
Imax = np.max(img)
Imin = np.min(img)
newImg = (img - Imin) / (Imax - Imin) * 255
newImg = newImg.astype(np.uint8)
cv2.imshow('newImg',newImg)
cv2.waitKey(0)
cv2.destroyAllWindows()

窗口窗位调整

滤波

线性滤波器

       线性滤波器主要由原图像、滤波算子组成,以3×3大小的算子为例,从原图像左上角开始滑动,遍历整个图像,每滑动到一处,就计算算子与算子所在的3×3图像对应位置的乘积,最后求和,得到一个数,将该数赋值给新图像对应位置即可。

       不过,算子滑动不可能超出原图像边界,所以新图像总有赋不到值的地方,我们希望通过一些填充手段,塞满无赋值区域。目前常见的有零填塞、常数填塞、夹取填塞、重叠填塞、镜像填塞和延长。

       线性滤波算子主要有均值算子、平移算子、Sobel算子、Scharr算子、Laplace算子、锐化算子、高斯算子等。

mean filter=\frac{1}{9}\begin{bmatrix} 1 &1 &1 \\ 1 &1 &1 \\ 1 &1 &1 \end{bmatrix}

moving filter=\begin{bmatrix} 0 & 0 & 0\\ 0& 0 & 1\\ 0& 0& 0 \end{bmatrix}

Sobel filter,G_{x}=\begin{bmatrix} -1 & 0 & 1\\ -2 & 0 & 2\\ -1& 0 & 1 \end{bmatrix},G_{y}=\begin{bmatrix} -1 & -2 &-1 \\ 0& 0 &0 \\ 1& 2& 1 \end{bmatrix}

Scharr filter,G_{x}=\begin{bmatrix} -3 & 0 & 3\\ -10& 0 &10\\ -3 & 0 & 3 \end{bmatrix},G_{y}=\begin{bmatrix} -3 & -10 & -3\\ 0 & 0 & 0\\ 3 &10 &3 \end{bmatrix}

Laplace filter=\begin{bmatrix} 0 & 1 & 0\\ 1 & -4 & 1\\ 0 & 1 & 0 \end{bmatrix}

sharpening filter=\begin{bmatrix} 0 & 0 & 0\\ 0 & 2 & 0\\ 0 & 0 & 0 \end{bmatrix}-\frac{1}{9}\begin{bmatrix} 1 & 1 & 1\\ 1 & 1 & 1\\ 1 & 1 & 1 \end{bmatrix}

       以下为Sobel算子的代码,它在求图像梯度,进行边缘检测上有很大用处。

import cv2
import numpy as np

def Filter(img):
    core_size = 3
    # 零填充
    pad = core_size//2
    newImg = np.zeros((img.shape[0]+2*pad,img.shape[1]+2*pad),dtype=np.uint8)
    newImg[pad:pad+img.shape[0],pad:pad+img.shape[1]] = img.astype(np.uint8)
    #滤波计算
    tmp = newImg.copy()
    core = np.array([[1,0,-1],[2,0,-2],[1,0,-1]])/9.0
    for y in range(img.shape[0]):
        for x in range(img.shape[1]):
            newImg[pad+y,pad+x] = np.sum(tmp[y:y+core_size,x:x+core_size]*core)
    newImg = newImg[pad:pad+img.shape[0],pad:pad+img.shape[1]].astype(np.uint8)
    return newImg

img = cv2.imread("image.png",0)
newImg = Filter(img)
cv2.imshow("img",img)
cv2.imshow("newImg",newImg)
cv2.waitKey(0)
cv2.destroyAllWindows()

       下面是原图像与滤波后图像:

       但是这样计算滤波,每个像素点要算(coreSize)^{2}次,如果能将滤波算子写成列向量×行向量的形式,每个像素点就只需要算2*coreSize次了,大大减轻运算负担,而专门针对x轴和y轴的滤波,对完成某些特定任务有很大帮助。

       如果觉得手动填充太麻烦,numpy.pad给了我们很方便的填充方式,如下,这也是opencv的sobel函数中默认的填充方式。

    filter = img.astype(np.int32)
    filter = np.pad(filter,((pad,pad),(pad,pad)),'reflect')

模板匹配

       将需要找寻的小图片作为滤波器,与原图像做处理。得出的图像哪里最亮,就说明哪里匹配度高。但作为找寻的图片,如果和原图像中的图不同(如被旋转、放缩等),则匹配度就不会很高。

高斯模糊

       高斯滤波,也叫高斯模糊,属于线性滤波器的一种,它让滤波算子的值符合高斯分布:

G_{\sigma }=\frac{1}{2\pi \sigma ^{2}}e^{-\frac{x^{2}+y^{2}}{2\sigma ^{2}}}

       其中,以3×3高斯算子为例,设中点为(0,0)点,依次求解,并归一化(这样就不会改变图片亮暗关系),以下是求高斯算子代码:

import numpy as np
import math
gaussian = np.zeros((3,3))
kesai = 1
for dx in range(-1,2):
    for dy in range(-1,2):
        gaussian[dx+1,dy+1] = (1/(2*kesai*math.pi))*math.exp(-((dx**2+dy**2)/(2*kesai**2)))
gaussian = gaussian/np.sum(gaussian)
print(gaussian)

高斯差分滤波器

       高斯差分滤波器是两个不同\sigma的高斯算子进行相减,能够提高滤波效率。

中值滤波

       中值滤波它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值,可以将窗口中心位置的像素值替换为该窗口内的中位数,可更好处理椒盐噪声、保留边缘。

频域分析

采样

       隔一定距离采样赋值给新图像,可以缩小图像,但图像会损失信息,变得模糊。

       如果采样频率小于2倍的信号频率,则会导致原本的高频信号被采样成低频信号,即高频信号被混叠成了低频信号,图像失真。如拍照频率不足的话,很可能看到正在行驶的车轮“向后转”。

傅里叶变换

卷积定理

图片融合

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python机器视觉是指使用Python编程语言进行图像处理和计算机视觉任务的领域。它涵盖了图像处理、图像分析、目标检测、图像识别等多个方面。在Python中,有一些常用的机器视觉库可以使用,如OpenCV、PIL等。通过这些库,我们可以读取、处理和分析图像数据,实现各种视觉任务。 在引用\[1\]中提到的代码中,使用了OpenCV库来打开并显示一张图片。首先,通过`import cv2`导入OpenCV库。然后,使用`cv2.imread("image1.png")`读取名为"image1.png"的图片。最后,使用`cv2.imshow("title", image)`显示图片窗口。 在引用\[2\]中提到了Python机器视觉的一些基础概念和编程基础知识,包括缩进、if语句、函数、类、循环、基础数据类型和基础数据结构等。 对于初学者来说,建议安装Anaconda发行版,它集成了常用的Python模块,并配置了方便的开发环境,如spyder和jupyter Notebook。可以从Anaconda官网下载适合自己操作系统的版本进行安装。同时,也可以通过搜索了解如何安装Python机器视觉模块。 #### 引用[.reference_title] - *1* *2* *3* [python机器人视觉编程——入门篇(上)](https://blog.csdn.net/kanbide/article/details/124926698)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值