数字图像与机器视觉基础补充(1)

这篇博客介绍了数字图像的基础知识,包括BMP图片的位图转换、文件头计算和大小分析。此外,还涉及图像处理编程任务,如使用奇异值分解(SVD)进行特征提取,以及通过开闭运算检测图像中的对象,如硬币和细胞。最后提到了条形码的定位和字符提取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一.实践操作

1.bmp图片不同位图

打开一个彩色图像文件,将其分别保存为 32位、16位彩色和256色、16色、单色的位图(BMP)文件,对比其文件大小,并计算分析这些图片在内存中的存储容量是多少?当保存为BMP文件时,将用文件头来记录图像的属性,
在这里插入图片描述

2.用notepad打开

ren1.bmp:
在这里插入图片描述
ren16.bmp:
在这里插入图片描述
ren256.bmp:
在这里插入图片描述

3.位图大小计算

位图大小计算公式为;长×高×位深度
在这里插入图片描述
512* 512 *1 / 8 / 1024=32 (kb)

4.头文件的大小计算:

0~1 两个字节为文件类型,0x4d42为固定BM
2~5 四个字节为文件大小,0x184e,即6222
6~9 四个字节为保留字段,全0
a~d 四个字节为从文件头到实际的位图数据的偏移字节数
12~15 四个字节表示图片宽度,0xdc为220
16~19 四个字节表示图片高度,0xdc为220
1a~1b 两个字节,恒定为0x1
1c~1d 两个字节表示像素占的比特,这里为0x1即两种颜色,16色为0x4即16种颜色,256色为0x8即256种颜色
1e~21 四个字节表示图片是否压缩,0x0表示不压缩
22~25 四个表示图像大小,0x1810为6160
26~29 四个字节表示水平分辨率
2a~2d 四个字节表示垂直分辨率
23~31 四个字节表示实际使用的颜色索引数
32~35 四个字节表示重要的颜色索引数

可以发现文件头一共占40个字节,为十六进制。

二.根据提供的资料完成以下图像处理编程任务

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

import numpy as np
import os
from PIL import Image
import matplotlib.pyplot as plt
import matplotlib as mpl
from pprint import pprint


def 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] = 0
    a[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] = 0
    a[a > 255] = 255
    return np.rint(a).astype('uint8')


if __name__ == "__main__":
    A = Image.open("E:/人工智能与机器学习/数字图像与机器视觉作业/人脸不同位图(BMP)文件/ren.jpg", 'r')
    print(A)
    output_path = r'E:/人工智能与机器学习/数字图像与机器视觉作业/人脸不同位图(BMP)文件/SVD_Output'
    if not os.path.exists(output_path):
        os.mkdir(output_path)
    a = np.array(A)
    print(a.shape)
    K = 50
    u_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'] = False
    for 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.采用图像的开闭运算(腐蚀-膨胀),检测出2个样本图像中硬币、细胞的个数。

import cv2
import numpy as np

def stackImages(scale, imgArray):
  
    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] * rows
        hor_con = [imageBlank] * rows
        for 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 = hor
    return ver


#读取图片
src = cv2.imread("img_1.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)

在这里插入图片描述

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

import cv2
import numpy as np
import imutils
from pyzbar import pyzbar
def stackImages(scale, imgArray):
    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] * rows
        hor_con = [imageBlank] * rows
        for 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 = hor
    return ver


#读取图片
src = cv2.imread("img_3.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, 10.0, (255, 0, 0), 30)
cv2.putText(img_1, "gray", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 10.0, (255, 0, 0), 30)
cv2.putText(img_2, "GaussianBlur",(200, 200), cv2.FONT_HERSHEY_SIMPLEX, 10.0, (255, 0, 0), 30)
cv2.putText(img_3, "Sobel", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 10.0, (255, 0, 0), 30)
cv2.putText(img_4, "blur", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 10.0, (255, 0, 0), 30)
cv2.putText(img_5, "threshold", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 10.0, (255, 0, 0), 30)
cv2.putText(img_6, "close", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 10.0, (255, 0, 0), 30)
cv2.putText(img_7, "open", (200, 200), cv2.FONT_HERSHEY_SIMPLEX, 10.0, (255, 0, 0), 30)

#输出条形码
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.1, ([img_1, img_2,img_3,img_4],[img_5,img_6,img_7,img]))
cv2.imshow("imgStack", imgStack)
cv2.waitKey(0)


添加链接描述在这里插入图片描述

三.参考

图像基本处理——腐蚀和膨胀
图像基本处理——图像阈值和平滑
OpenCV简单实践之数字图像与机器视觉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值