admin 管理员组

文章数量: 887017

数学图形与机器视觉基础(1)

文章目录

  • 一、图片处理及分析
      • 1.修改图片位数和颜色并进行分析
      • 2.修改图片格式并进行分析
  • 二、用奇异值分解(SVD)对一张图片进行特征值提取(降维)处理
  • 三、采用图像的开闭运算(腐蚀-膨胀),检测出2个样本图像中硬币、细胞的个数
  • 四、采用图像梯度、开闭、轮廓运算等,对图片中的条形码进行定位提取;再调用条码库获得条码字符

一、图片处理及分析

1.修改图片位数和颜色并进行分析

原图如下,首先将其分别保存为 32位、16位彩色和256色、16色、单色的位图(BMP)文件。

以下分别为16位,32位位彩色位图文件

以下分别为256色,16色,单色的位图文件

1、“大小”是文件的实际字节数,而“占用空间”的是在磁盘上占用的字节数。
2、“占用空间”通常比“大小”要大,但也可以和“大小”一样。
一个文件或文件夹属性中的“大小(Size)”和“占用空间(Size on disk)”通常不相互匹配。“大小”的值表示文件实际大小的字节数,而“占用空间”的值表文件占用硬盘空间大小的字节数。
这种差异来自文件系统在驱动器上存储的文件的方式。为了减少使用的地址数量,文件系统把一定数量的字节当成簇。根据不同的文件系统,常见的簇大小可以从2KB的到32KB。一个被写入到磁盘的文件需要占用若干个不相连的簇,而无论文件的实际大小。因此,一个1KB的文件,保存在一个簇大小为2KB的文件系统将占用2KB,但保存在一个簇大小为32KB的文件系统,它会占用32KB。也就是说,一个33KB的文件将占用17个2KB的簇(34KB)或2个32KB的簇(64KB)。

位图文件头分4部分,共14字节:
bfType:2字节,作为标识,就是“BM”二字。
bfSize:4字节,整个BMP文件的大小。
bfReserved1/2:4字节,保留字,没用。
bfOffBits:4字节,偏移数,即 位图文件头+位图信息头+调色板 的大小。

2.修改图片格式并进行分析

将一幅彩色照片分别保存为BMP、JPG、GIF和PNG格式,对比它们的文件大小比,判断图像的压缩保存后的压缩比率。

以下分别为BMP、JPG、GIF和PNG格式图片

图片格式压缩比例
BMP(原图)1
JP14%
GIF21%
PNG57%

二、用奇异值分解(SVD)对一张图片进行特征值提取(降维)处理

代码:

import numpy as np
import os
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib as mpl
from pprint import pprintdef restore1(sigma, u, v, K):  # 奇异值、左特征向量、右特征向量m = len(u)n = len(v[0])a = np.zeros((m, n))for k in range(K):uk = u[:, k].reshape(m, 1)vk = v[k].reshape(1, n)a += sigma[k] * np.dot(uk, vk)a[a < 0] = 0a[a > 255] = 255# a = a.clip(0, 255)return np.rint(a).astype('uint8')def restore2(sigma, u, v, K):  # 奇异值、左特征向量、右特征向量m = len(u)n = len(v[0])a = np.zeros((m, n))for k in range(K+1):for i in range(m):a[i] += sigma[k] * u[i][k] * v[k]a[a < 0] = 0a[a > 255] = 255return np.rint(a).astype('uint8')if __name__ == "__main__":A = Image.open("./lena.jpg", 'r')print(A)output_path = r'./SVD_Output'if not os.path.exists(output_path):os.mkdir(output_path)a = np.array(A)print(a.shape)K = 50u_r, sigma_r, v_r = np.linalg.svd(a[:, :, 0])u_g, sigma_g, v_g = np.linalg.svd(a[:, :, 1])u_b, sigma_b, v_b = np.linalg.svd(a[:, :, 2])plt.figure(figsize=(11, 9), facecolor='w')mpl.rcParams['font.sans-serif'] = ['simHei']mpl.rcParams['axes.unicode_minus'] = Falsefor k in range(1, K+1):print(k)R = restore1(sigma_r, u_r, v_r, k)G = restore1(sigma_g, u_g, v_g, k)B = restore1(sigma_b, u_b, v_b, k)I = np.stack((R, G, B), axis=2)Image.fromarray(I).save('%s\\svd_%d.png' % (output_path, k))if k <= 12:plt.subplot(3, 4, k)plt.imshow(I)plt.axis('off')plt.title('奇异值个数:%d' % k)plt.suptitle('SVD与图像分解', fontsize=20)plt.tight_layout()# plt.subplots_adjust(top=0.9)plt.show()

运行如下:

三、采用图像的开闭运算(腐蚀-膨胀),检测出2个样本图像中硬币、细胞的个数

代码:

import cv2
import numpy as npdef stackImages(scale, imgArray):"""将多张图像压入同一个窗口显示:param scale:float类型,输出图像显示百分比,控制缩放比例,0.5=图像分辨率缩小一半:param imgArray:元组嵌套列表,需要排列的图像矩阵:return:输出图像"""rows = len(imgArray)cols = len(imgArray[0])rowsAvailable = isinstance(imgArray[0], list)width = imgArray[0][0].shape[1]height = imgArray[0][0].shape[0]if rowsAvailable:for x in range(0, rows):for y in range(0, cols):if imgArray[x][y].shape[:2] == imgArray[0][0].shape[:2]:imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)else:imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]),None, scale, scale)if len(imgArray[x][y].shape) == 2: imgArray[x][y] = cv2.cvtColor(imgArray[x][y], cv2.COLOR_GRAY2BGR)imageBlank = np.zeros((height, width, 3), np.uint8)hor = [imageBlank] * rowshor_con = [imageBlank] * rowsfor x in range(0, rows):hor[x] = np.hstack(imgArray[x])ver = np.vstack(hor)else:for x in range(0, rows):if imgArray[x].shape[:2] == imgArray[0].shape[:2]:imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)else:imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None, scale, scale)if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)hor = np.hstack(imgArray)ver = horreturn ver#读取图片
src = cv2.imread("coin.png")
img = src.copy()#灰度
img_1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#二值化
ret, img_2 = cv2.threshold(img_1, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)#腐蚀
kernel = np.ones((20, 20), int)
img_3 = cv2.erode(img_2, kernel, iterations=1)#膨胀
kernel = np.ones((3, 3), int)
img_4 = cv2.dilate(img_3, kernel, iterations=1)#找到硬币中心
contours, hierarchy = cv2.findContours(img_4, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2:]#标识硬币
cv2.drawContours(img, contours, -1, (0, 0, 255), 5)#显示图片
cv2.putText(img, "count:{}".format(len(contours)), (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(src, "src", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_1, "gray", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_2, "thresh", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_3, "erode", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_4, "dilate", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
imgStack = stackImages(1, ([src, img_1, img_2], [img_3, img_4, img]))
cv2.imshow("imgStack", imgStack)
![cv2.waitKey(0)

运行如下:

import cv2
import numpy as npdef stackImages(scale, imgArray):"""将多张图像压入同一个窗口显示:param scale:float类型,输出图像显示百分比,控制缩放比例,0.5=图像分辨率缩小一半:param imgArray:元组嵌套列表,需要排列的图像矩阵:return:输出图像"""rows = len(imgArray)cols = len(imgArray[0])rowsAvailable = isinstance(imgArray[0], list)width = imgArray[0][0].shape[1]height = imgArray[0][0].shape[0]if rowsAvailable:for x in range(0, rows):for y in range(0, cols):if imgArray[x][y].shape[:2] == imgArray[0][0].shape[:2]:imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)else:imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]),None, scale, scale)if len(imgArray[x][y].shape) == 2: imgArray[x][y] = cv2.cvtColor(imgArray[x][y], cv2.COLOR_GRAY2BGR)imageBlank = np.zeros((height, width, 3), np.uint8)hor = [imageBlank] * rowshor_con = [imageBlank] * rowsfor x in range(0, rows):hor[x] = np.hstack(imgArray[x])ver = np.vstack(hor)else:for x in range(0, rows):if imgArray[x].shape[:2] == imgArray[0].shape[:2]:imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)else:imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None, scale, scale)if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)hor = np.hstack(imgArray)ver = horreturn ver#读取图片
src = cv2.imread("cell.png")
img = src.copy()#灰度
img_1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#二值化
ret, img_2 = cv2.threshold(img_1, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)#腐蚀
kernel = np.ones((20, 20), int)
img_3 = cv2.erode(img_2, kernel, iterations=1)#膨胀
kernel = np.ones((3, 3), int)
img_4 = cv2.dilate(img_3, kernel, iterations=1)#找到硬币中心
contours, hierarchy = cv2.findContours(img_4, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2:]#标识硬币
cv2.drawContours(img, contours, -1, (0, 0, 255), 5)#显示图片
cv2.putText(img, "count:{}".format(len(contours)), (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(src, "src", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_1, "gray", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_2, "thresh", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_3, "erode", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_4, "dilate", (0, 30), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
imgStack = stackImages(1, ([src, img_1, img_2], [img_3, img_4, img]))
cv2.imshow("imgStack", imgStack)
cv2.waitKey(0)

运行如下:

四、采用图像梯度、开闭、轮廓运算等,对图片中的条形码进行定位提取;再调用条码库获得条码字符

代码:

import cv2
import numpy as np
import imutils
from pyzbar import pyzbar
def stackImages(scale, imgArray):"""将多张图像压入同一个窗口显示:param scale:float类型,输出图像显示百分比,控制缩放比例,0.5=图像分辨率缩小一半:param imgArray:元组嵌套列表,需要排列的图像矩阵:return:输出图像"""rows = len(imgArray)cols = len(imgArray[0])rowsAvailable = isinstance(imgArray[0], list)width = imgArray[0][0].shape[1]height = imgArray[0][0].shape[0]if rowsAvailable:for x in range(0, rows):for y in range(0, cols):if imgArray[x][y].shape[:2] == imgArray[0][0].shape[:2]:imgArray[x][y] = cv2.resize(imgArray[x][y], (0, 0), None, scale, scale)else:imgArray[x][y] = cv2.resize(imgArray[x][y], (imgArray[0][0].shape[1], imgArray[0][0].shape[0]),None, scale, scale)if len(imgArray[x][y].shape) == 2: imgArray[x][y] = cv2.cvtColor(imgArray[x][y], cv2.COLOR_GRAY2BGR)imageBlank = np.zeros((height, width, 3), np.uint8)hor = [imageBlank] * rowshor_con = [imageBlank] * rowsfor x in range(0, rows):hor[x] = np.hstack(imgArray[x])ver = np.vstack(hor)else:for x in range(0, rows):if imgArray[x].shape[:2] == imgArray[0].shape[:2]:imgArray[x] = cv2.resize(imgArray[x], (0, 0), None, scale, scale)else:imgArray[x] = cv2.resize(imgArray[x], (imgArray[0].shape[1], imgArray[0].shape[0]), None, scale, scale)if len(imgArray[x].shape) == 2: imgArray[x] = cv2.cvtColor(imgArray[x], cv2.COLOR_GRAY2BGR)hor = np.hstack(imgArray)ver = horreturn ver#读取图片
src = cv2.imread("D:\ai\13zhou\picture\\txm.jpg")
img = src.copy()#灰度
img_1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#高斯滤波
img_2 = cv2.GaussianBlur(img_1, (5, 5), 1)#Sobel算子
sobel_x = cv2.Sobel(img_2, cv2.CV_64F, 1, 0, ksize=3)
sobel_y = cv2.Sobel(img_2, cv2.CV_64F, 0, 1, ksize=3)
sobel_x = cv2.convertScaleAbs(sobel_x)
sobel_y = cv2.convertScaleAbs(sobel_y)
img_3 = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)#均值方波
img_4 = cv2.blur(img_3, (5, 5))#二值化
ret, img_5 = cv2.threshold(img_4, 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)#闭运算
kernel = np.ones((100, 100), int)
img_6 = cv2.morphologyEx(img_5, cv2.MORPH_CLOSE, kernel)#开运算
kernel = np.ones((200, 200), int)
img_7 = cv2.morphologyEx(img_6, cv2.MORPH_OPEN, kernel)#绘制条形码区域
contours = cv2.findContours(img_7, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
c = sorted(contours, key = cv2.contourArea, reverse = True)[0]
rect = cv2.minAreaRect(c)
box = cv2.cv.BoxPoints(rect) if imutils.is_cv2() else cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(img, [box], -1, (0,255,0), 20)#显示图片信息
cv2.putText(img, "results", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_1, "gray", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), 3)
cv2.putText(img_2, "GaussianBlur",(200, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), 3)
cv2.putText(img_3, "Sobel", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_4, "blur", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_5, "threshold", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (255, 0, 0), 3)
cv2.putText(img_6, "close", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), 3)
cv2.putText(img_7, "open", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 1.0, (0, 0, 0), 3)#输出条形码
barcodes = pyzbar.decode(src)
for barcode in barcodes:barcodeData = barcode.data.decode("utf-8")cv2.putText(img, barcodeData, (200, 600), cv2.FONT_HERSHEY_SIMPLEX, 5.0, (0, 255, 0), 30)#显示所有图片
imgStack = stackImages(0.8, ([img_1, img_2],[img_3,img_4],[img_5,img_6],[img_7,img]))
cv2.imshow("imgStack", imgStack)
cv2.waitKey(0)

运行如下:

本文标签: 数学图形与机器视觉基础(1)