【图像处理】传统图像处理方式及opencv实现


前言

传统图像处理是指使用经典的图像处理技术和方法,这些方法在计算机视觉和图像处理领域的早期阶段得到广泛应用。以下是一些传统图像处理的主要方法:


一、灰度转换

将彩色图像转换为灰度图像,使每个像素只包含亮度信息而不包含颜色信息。这通常是图像处理的第一步,常结合后续的一些算法进行操作。

import cv2
import numpy as np

if __name__ == '__main__':
    img = cv2.imread('car.jpg', 1)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    cv2.imshow('img_gray', img_gray)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

原图:
在这里插入图片描述
转换后:
在这里插入图片描述

二、滤波器和图像梯度

使用滤波器和卷积操作对图像进行平滑、锐化、边缘检测等处理。常用的滤波器包括均值滤波、高斯滤波、Sobel滤波器等。

1、图像平滑

使用cv2.filter2D进行平滑操作。卷积核:
在这里插入图片描述

import cv2
import numpy as np

if __name__ == '__main__':
    img = cv2.imread('car.jpg', 1)
    # img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    kernel = np.ones((5, 5), np.float32) / 25
    dst = cv2.filter2D(img, -1, kernel)
    
    cv2.imwrite('dst.jpg', dst)
    cv2.imshow('dst', dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

在这里插入图片描述
图像平滑,常用于消除高频部分(例如噪声、边缘)。opencv提供4种类型的模糊方式:
(1)平均模糊:cv2.blur()或cv2.boxFilter();(2)高斯模糊: cv2.GaussianBlur();(3)中位模糊:cv2.medianBlur();(4)双边模糊:cv.bilateralFilter()。

2、图像梯度

OpenCV提供三种类型的算子,即Sobel,Scharr和Laplacian用于获取图像梯度。
Sobel算子是高斯平滑加微分的联合运算。Sobel分为x和y方向。
Laplacian 算子的每一阶导数通过Sobel算子计算。
在这里插入图片描述

import cv2
import matplotlib.pyplot as plt

if __name__ == '__main__':
    img = cv2.imread('staff.jpeg', 0)
    laplacian = cv2.Laplacian(img, cv2.CV_64F, ksize=3)
    sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=5)
    sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=5)
    plt.subplot(2, 2, 1), plt.imshow(img, cmap='gray')
    plt.title('Original'), plt.xticks([]), plt.yticks([])
    plt.subplot(2, 2, 2), plt.imshow(laplacian, cmap='gray')
    plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
    plt.subplot(2, 2, 3), plt.imshow(sobelx, cmap='gray')
    plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
    plt.subplot(2, 2, 4), plt.imshow(sobely, cmap='gray')
    plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
    plt.show()

三、直方图均衡化

通过调整图像的亮度分布,增强图像的对比度,使图像更容易分析和处理。一副好的图像有来自图像所有区域的像素,而不是仅仅局限于某个特定的值范围。
在这里插入图片描述

import cv2
import numpy as np

if __name__ == '__main__':
    img = cv2.imread('car.jpg', 0)
    equ = cv2.equalizeHist(img)
    res = np.hstack((img, equ))  # stacking images side-by-side
    cv2.imwrite('res.jpg', res)

在这里插入图片描述

四、形态学处理

利用基本形态学操作,如膨胀和腐蚀,进行图像的形状和结构的处理,常用于图像分割和去噪。
腐蚀操作:原始图像中的一个像素(无论是1还是0)只有当kernel下的所有像素都是1时才被认为是1,否则它就会被腐蚀(变成0)。
膨胀操作:与腐蚀操作相反。kernel下至少有一个像素为1,就会被认为是1。该操作会增加前景对象的大小
开运算:先进行腐蚀操作再膨胀。
闭运算:先膨胀再腐蚀。
形态学梯度:膨胀后的图像减去侵蚀后的图像。
顶帽:原始图像减去开运算后的图像。
黑帽:原始图像减去闭运算后的图像。

import cv2
import numpy as np
import matplotlib.pyplot as plt

if __name__ == '__main__':
    img = cv2.imread('j.png', 0)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    kernel = np.ones((5, 5), np.uint8)
    erosion = cv2.erode(img, kernel, iterations=1)  # 腐蚀
    dilation = cv2.dilate(img, kernel, iterations=1)  # 膨胀
    opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)  # 开运算
    closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)  # 闭运算
    gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)  # 梯度
    tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)  # 顶帽
    blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)  # 黑帽
    plt.figure(figsize=(10, 10))
    plt.subplot(2, 4, 1), plt.imshow(img), plt.title('Original')
    plt.xticks([]), plt.yticks([])
    plt.subplot(2, 4, 2), plt.imshow(erosion), plt.title('Erosion')
    plt.xticks([]), plt.yticks([])
    plt.subplot(2, 4, 3), plt.imshow(dilation), plt.title('Dilation')
    plt.xticks([]), plt.yticks([])
    plt.subplot(2, 4, 4), plt.imshow(opening), plt.title('Opening')
    plt.xticks([]), plt.yticks([])
    plt.subplot(2, 4, 5), plt.imshow(closing), plt.title('Closing')
    plt.xticks([]), plt.yticks([])
    plt.subplot(2, 4, 6), plt.imshow(gradient), plt.title('Gradient')
    plt.xticks([]), plt.yticks([])
    plt.subplot(2, 4, 7), plt.imshow(tophat), plt.title('Tophat')
    plt.xticks([]), plt.yticks([])
    plt.subplot(2, 4, 8), plt.imshow(blackhat), plt.title('Blackhat')
    plt.xticks([]), plt.yticks([])
    plt.show()

在这里插入图片描述

五、图像阈值

对图像进行二值化处理,凸显自己感兴趣的区域。阈值化处理常常是图像处理的前序步骤。

import cv2 as cv
from matplotlib import pyplot as plt

if __name__ == '__main__':
    img = cv.imread('car.jpg', 0)
    ret, thresh1 = cv.threshold(img, 127, 255, cv.THRESH_BINARY)
    ret, thresh2 = cv.threshold(img, 127, 255, cv.THRESH_BINARY_INV)
    ret, thresh3 = cv.threshold(img, 127, 255, cv.THRESH_TRUNC)
    ret, thresh4 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO)
    ret, thresh5 = cv.threshold(img, 127, 255, cv.THRESH_TOZERO_INV)
    titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
    images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
    for i in range(6):
        plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
        plt.title(titles[i])
        plt.xticks([]), plt.yticks([])
    plt.show()

在这里插入图片描述

六、特征提取

从图像中提取出具有代表性的特征,如纹理、形状、颜色等,用于图像识别和分类。
常见的算法有:哈里斯角点检测、霍夫直线变换、SIFT算法等。

import numpy as np
import cv2 as cv
filename = 'chessboard.png'
img = cv.imread(filename)
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv.cornerHarris(gray,2,3,0.04)
#result用于标记角点,并不重要
dst = cv.dilate(dst,None)
#最佳值的阈值,它可能因图像而异。
img[dst>0.01*dst.max()]=[0,0,255]
cv.imshow('dst',img)
if cv.waitKey(0) & 0xff == 27:
    cv.destroyAllWindows()

七、几何变换

包括平移、旋转、缩放等基本的几何变换,用于调整图像的大小和位置。
1、缩放

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC)
#或者
height, width = img.shape[:2]
res = cv.resize(img,(2*width, 2*height), interpolation = cv.INTER_CUBIC)

2、平移
在这里插入图片描述

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv.warpAffine(img,M,(cols,rows))
cv.imshow('img',dst)
cv.waitKey(0)
cv.destroyAllWindows()

3、旋转
在这里插入图片描述

img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
# cols-1 和 rows-1 是坐标限制
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv.warpAffine(img,M,(cols,rows))

4、仿射变换
在仿射变换中,原始图像中的所有平行线在输出图像中仍将平行。为了找到变换矩阵,我们需要输入图像中的三个点及其在输出图像中的对应位置。然后cv.getAffineTransform将创建一个2x3矩阵,该矩阵将传递给cv.warpAffine
在这里插入图片描述

img = cv.imread('drawing.png')
rows,cols,ch = img.shape
pts1 = np.float32([[50,50],[200,50],[50,200]])
pts2 = np.float32([[10,100],[200,50],[100,250]])
M = cv.getAffineTransform(pts1,pts2)
dst = cv.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')

5、透视变换
对于透视变换,您需要3x3变换矩阵。即使在转换后,直线也将保持直线。要找到此变换矩阵,您需要在输入图像上有4个点,在输出图像上需要相应的点。在这四个点中,其中三个不应共线。然后可以通过函数cv.getPerspectiveTransform找到变换矩阵。然后将cv.warpPerspective应用于此3x3转换矩阵。

img = cv.imread('sudoku.png')
rows,cols,ch = img.shape
pts1 = np.float32([[56,65],[368,52],[28,387],[389,390]])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])
M = cv.getPerspectiveTransform(pts1,pts2)
dst = cv.warpPerspective(img,M,(300,300))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

在这里插入图片描述

八、图像压缩

使用各种压缩算法减小图像文件的大小,而尽量保持图像质量。JPEG、PNG等是常见的图像压缩格式。

九、图像融合

将多个图像或图像的不同部分合并成一个图像,常用于医学图像处理和计算机视觉领域。

import cv2 as cv
img1 = cv.imread('ml.png')
img2 = cv.imread('opencv-logo.png')
dst = cv.addWeighted(img1,0.7,img2,0.3,0)
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()

十、边缘检测

识别图像中物体之间的边缘,常用于图像分割和目标检测,常用算法有:Canny角点检测。

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg',0)
edges = cv.Canny(img,100,200)
plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()

总结

以上是对常用的传统图像处理方式的总结。
参考链接

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是一个基于传统图像处理方法的车牌字符识别示例代码: ```python import cv2 import numpy as np # 加载字符模板 template_images = [] for i in range(10): template_image = cv2.imread(f'template_{i}.jpg', 0) template_images.append(template_image) # 读取车牌图像 plate_image = cv2.imread('plate_image.jpg', 0) # 预处理车牌图像 _, plate_image = cv2.threshold(plate_image, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) plate_image = cv2.medianBlur(plate_image, 3) # 字符分割 contours, _ = cv2.findContours(plate_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) characters = [] for contour in contours: # 忽略过小的轮廓 if cv2.contourArea(contour) < 100: continue # 获取字符区域的矩形框坐标 x, y, w, h = cv2.boundingRect(contour) # 提取字符图像 character_roi = plate_image[y:y+h, x:x+w] # 调整字符图像大小为模板大小 character_roi = cv2.resize(character_roi, (template_images[0].shape[1], template_images[0].shape[0])) # 字符匹配 scores = [] for template in template_images: score = cv2.matchTemplate(character_roi, template, cv2.TM_CCOEFF_NORMED) scores.append(score) # 获取最佳匹配字符 best_match_index = np.argmax(scores) character = str(best_match_index) characters.append(character) # 输出识别结果 plate_number = ''.join(characters) print("车牌号码:", plate_number) ``` 在代码中,首先加载字符模板图像,它们包含了数字0到9的样本字符图像。然后读取待识别的车牌图像,并进行预处理操作,例如二值化和中值滤波。接下来,使用`findContours`函数找到字符的轮廓,并遍历每个字符轮廓。对于每个字符区域,首先调整大小为模板大小,然后使用`matchTemplate`函数与所有模板进行匹配得分计算。最后,根据得分选择最佳匹配字符,并将其存储在结果中。 请注意,上述代码仅用于演示目的,实际应用中可能需要根据具体情况进行调整和优化。此外,传统图像处理方法在复杂场景下的效果可能不如基于深度学习的方法。因此,对于更高精度和鲁棒性的车牌字符识别任务,建议使用基于深度学习的方法

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值