day1¶
1.opencv识别书脊标签¶
import cv2
import numpy as np
# 读取图像
image = cv2.imread('IMG20240614164102.jpg')
# 确保图像已正确读取
if image is None:
print("Error: Could not open or find the image")
exit()
# 将图像从BGR转换到HSV
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
# 定义绿色的HSV范围
lower_green = np.array([35, 100, 100])
upper_green = np.array([77, 255, 255])
# 创建一个二值图像,其中只有绿色区域被标记为白色
mask = cv2.inRange(hsv, lower_green, upper_green)
# 使用位操作将原始图像中的非绿色区域设置为黑色
# 这里我们用掩码来提取绿色区域,并将其放置在一张全黑的背景上
result = cv2.bitwise_and(image, image, mask=mask)
# 为了确保背景完全是黑色,我们可以将非绿色区域设置为0
result[mask == 0] = [0, 0, 0]
# 显示原始图像和只包含绿色标签的图像
cv2.imshow('Original Image', image)
cv2.imshow('Image with only Green Labels', result)
# 等待用户按键,然后关闭窗口
cv2.waitKey(0)
cv2.destroyAllWindows()
2.连接服务器¶
3.上传文件到GitHub¶
day 2¶
1.opencv轮廓检测框出数字¶
import cv2
import os
import numpy as np
def crop_green_label_and_detect_numbers(image_folder):
# 遍历图片文件夹
for filename in os.listdir(image_folder):# 这个函数用于列出指定目录下的所有文件和目录名,但不包括子目录中的文件。
#print(filename) #1.jpg | 2.jpg
if filename.lower().endswith(('.png', '.jpg', '.jpeg')):# 检查文件名是否以指定的图片格式结尾
img_path = os.path.join(image_folder, filename)
img = cv2.imread(img_path)
if img is None:
print(f"Error: Unable to read {img_path}")
continue
# os.path.join函数将image_folder和filename合并成一个完整的文件路径,并将结果存储在img_path变量中。
# 转换到HSV色彩空间
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 定义绿色的HSV范围
lower_green = np.array([36, 25, 25])
upper_green = np.array([70, 255, 255])
# 创建一个掩模来分割绿色
mask_green = cv2.inRange(hsv, lower_green, upper_green)
# 找到掩模中的轮廓
contours, _ = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 假设最大的轮廓是绿色标签(可能需要根据实际情况调整)
if contours:
max_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(max_contour)
# 裁剪绿色标签
cropped_label = img[y:y + h, x:x + w]
# cv2.imshow("2",cropped_label)
# 对裁剪后的标签进行灰度转换和阈值化处理
gray_label = cv2.cvtColor(cropped_label, cv2.COLOR_BGR2GRAY)
# 二值化
_, thresh_label = cv2.threshold(gray_label, 127, 255, cv2.THRESH_BINARY_INV)
cv2.bitwise_not(thresh_label, thresh_label)
# 开运算
kernel = np.ones((3, 3), np.uint8)
thresh_label = cv2.morphologyEx(thresh_label, cv2.MORPH_CLOSE, kernel)
# 膨胀
thresh_label = cv2.erode(thresh_label, kernel)
# thresh_label = cv2.erode(thresh_label, kernel)
cv2.imshow("sh", thresh_label)
# 查找所有轮廓
contours_numbers, _ = cv2.findContours(thresh_label, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv2.imshow("sh", thresh_label)
draw = cropped_label.copy()
list1 = []
# 循环轮廓
for contours_number in contours_numbers:
x, y, w, h = cv2.boundingRect(contours_number)
S = w * h
#设定膨胀面积
if S < 100000 and S > 300:
list1.append(contours_number)
res = cv2.drawContours(draw, list1, -1, (0, 0, 255), 2)
cv2.imshow('res', draw)
draw2 = cropped_label.copy()
# 遍历轮廓并框出每个数字
for cnt in list1:
x, y, w, h = cv2.boundingRect(cnt)
if w > 2 and h > 2: # 根据数字的大小设置阈值
cv2.rectangle(draw2, (x, y), (x + w, y + h), (0, 0, 255), 2) # 框出数字
# 显示结果(可选:保存结果或进一步处理)
cv2.imshow(f'1', draw2)
cv2.waitKey(0)
# cv2.destroyAllWindows()
cv2.destroyAllWindows()
def crop_green_label_and_detect_numbers2(img_path):
img = cv2.imread(img_path)
# 转换到HSV色彩空间
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 定义绿色的HSV范围
lower_green = np.array([36, 25, 25])
upper_green = np.array([70, 255, 255])
# 创建一个掩模来分割绿色
mask_green = cv2.inRange(hsv, lower_green, upper_green)
# 找到掩模中的轮廓
contours, _ = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 假设最大的轮廓是绿色标签(可能需要根据实际情况调整)
if contours:
max_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(max_contour)
# 裁剪绿色标签
cropped_label = img[y:y + h, x:x + w]
# cv2.imshow("2",cropped_label)
# 对裁剪后的标签进行灰度转换和阈值化处理
gray_label = cv2.cvtColor(cropped_label, cv2.COLOR_BGR2GRAY)
# 二值化
_, thresh_label = cv2.threshold(gray_label, 127, 255, cv2.THRESH_BINARY_INV)
cv2.bitwise_not(thresh_label, thresh_label)
# 开运算
kernel = np.ones((3, 3), np.uint8)
thresh_label = cv2.morphologyEx(thresh_label, cv2.MORPH_CLOSE, kernel)
# 膨胀
thresh_label = cv2.erode(thresh_label, kernel)
# thresh_label = cv2.erode(thresh_label, kernel)
cv2.imshow("sh", thresh_label)
# 查找所有轮廓
contours_numbers, _ = cv2.findContours(thresh_label, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv2.imshow("sh", thresh_label)
draw = cropped_label.copy()
list1 = []
# 循环轮廓
for contours_number in contours_numbers:
x, y, w, h = cv2.boundingRect(contours_number)
S = w * h
#设定膨胀面积
if S < 100000 and S > 300:
list1.append(contours_number)
res = cv2.drawContours(draw, list1, -1, (0, 0, 255), 2)
cv2.imshow('res', draw)
draw2 = cropped_label.copy()
# 遍历轮廓并框出每个数字
for cnt in list1:
x, y, w, h = cv2.boundingRect(cnt)
if w > 2 and h > 2: # 根据数字的大小设置阈值
cv2.rectangle(draw2, (x, y), (x + w, y + h), (0, 0, 255), 2) # 框出数字
# 显示结果(可选:保存结果或进一步处理)
cv2.imshow(f'1', draw2)
cv2.imwrite("./tushu/photo.jpg",draw2)
cv2.waitKey(0)
cv2.destroyAllWindows()
if __name__=="__main__":
# path=r"./tushu/3.jpg"
# crop_green_label_and_detect_numbers2(path)
# # 替换为你的图片文件夹路径
image_folder = r'./tushu'
crop_green_label_and_detect_numbers(image_folder)
day 3¶
1.模板匹配¶
模板是被查找的图像。模板匹配是指查找模板在原始图像中的哪个位置的过程。
image: 原始图像
templ: 模板图像,尺寸必须小于或等于原始图像
method: 匹配的方法 mask:(可选)掩模,只有 cv2.TM_SQDIFF和 c2.TM_CCORR_NORMED 支持此参数,建议采用默认值 result: 计算得出的匹配结果。如果原始图像的宽、高分别为 W、H,模板图像的宽、高分别为 w、h,result 就是一个 W-w+1列、H-h+1行的32位浮点型数组。数组中每个浮点数都是原始图像中对应像素位置的匹配结果,其含义需要根据 method 参数来解读
retval是一个矩阵,大小为(N-M+1, M-N+1),其中N和M分别为大图像和小图像的高和宽。矩阵中的每个元素表示原始图像中与模板匹配度的一个指标,匹配越好,则值越大。
单模板匹配¶
匹配过程中只用到一个模板的场景叫单模板匹配。原始图像中可能只有一个和模板相以的图像,也有可能有多个。如果只获取匹配程度最高的那一个结果,这种操作叫单目标配;如果需要同时获取所有匹配程度较高的结果,这种操作叫多目标匹配。
单目标匹配¶
单目标匹配只获取一个结果即可,就是匹配程度最高的结果 (如果使用平方差匹配,则为计算出的最小结果;如果使用相关匹配或相关系数匹配,则为计算出的最大结果)。本节以平方差匹配为例做介绍。
matchTemplate() 方法的计算结果是一个二维数组,minMaxLoc()方法专门用来解析这个二维数组中的最大值、最小值以及这两个值对应的坐标:
src: matchTemplate() 方法计算得出的数组 mask:(可选)掩模,建议使用默认值。 minValue: 数组中的最小值 maxValue: 数组中的最大值。 minLoc: 最小值的坐标,格式为(x,y)。 maxLoc: 最大值的坐标,格式为(x,y)。 平方差匹配的计算结果越小,匹配程度越高。minMaxLoc() 方法返回的 minValue 值是模板匹配的最优结果,minLoc 是最优结果区域左上角的点坐标,区域大小与模板大小一致。多目标匹配
多目标匹配¶
多目标匹配需要将原始图像中所有与模板相似的图像都找出来,使用相关匹配或相关系数匹配可以很好地实现这个功能。如果计算结果大于某一值,则认为匹配区域的图案和模板是相同的。
多模板匹配¶
匹配过程中同时查找多个模板的操作叫多模板匹配。多模板匹配实际上就是进行了n次“单模板多模板匹配”操作,n的数量为模板总数。
# 替换为你的模板文件夹路径
template_folder = r'D:\python\pythonProject2\tsg\mb'
templates,templates_id = load_templates_from_folder(template_folder)
#模板匹配的图片
my_list=[]
template_folder= r'D:\python\pythonProject2\tsg\cat'
for filename in os.listdir(template_folder):
# print("filename",filename )
file_path = os.path.join(template_folder, filename)
img=cv2.imread(file_path)
gray_label2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
matches = multi_template_match(gray_label2, templates,templates_id)
my_list.append(matches[0])
a="".join(my_list)
print(a)
def crop_green_label_and_detect_numbers2(img_path):
img = cv2.imread(img_path)
# 转换到HSV色彩空间
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# 定义绿色的HSV范围
lower_green = np.array([36, 25, 25])
upper_green = np.array([70, 255, 255])
# 创建一个掩模来分割绿色
mask_green = cv2.inRange(hsv, lower_green, upper_green)
# 找到掩模中的轮廓
contours, _ = cv2.findContours(mask_green, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 假设最大的轮廓是绿色标签(可能需要根据实际情况调整)
if contours:
max_contour = max(contours, key=cv2.contourArea)
x, y, w, h = cv2.boundingRect(max_contour)
# 裁剪绿色标签
cropped_label = img[y:y + h, x:x + w]
# cv2.imshow("2",cropped_label)
# 对裁剪后的标签进行灰度转换和阈值化处理
gray_label = cv2.cvtColor(cropped_label, cv2.COLOR_BGR2GRAY)
# 二值化
_, thresh_label = cv2.threshold(gray_label, 127, 255, cv2.THRESH_BINARY_INV)
cv2.bitwise_not(thresh_label, thresh_label)
# 开运算
kernel = np.ones((3, 3), np.uint8)
thresh_label = cv2.morphologyEx(thresh_label, cv2.MORPH_CLOSE, kernel)
# 膨胀
thresh_label = cv2.erode(thresh_label, kernel)
# thresh_label = cv2.erode(thresh_label, kernel)
cv2.imshow("sh", thresh_label)
# 查找所有轮廓
contours_numbers, _ = cv2.findContours(thresh_label, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv2.imshow("sh", thresh_label)
draw = cropped_label.copy()
list1 = []
# 循环轮廓
for contours_number in contours_numbers:
x, y, w, h = cv2.boundingRect(contours_number)
S = w * h
#设定膨胀面积
if S < 100000 and S > 300:
list1.append(contours_number)
res = cv2.drawContours(draw, list1, -1, (0, 0, 255), 2)
cv2.imshow('res', draw)
draw2 = cropped_label.copy()
def load_templates_from_folder(template_folder):
"""从指定文件夹加载模板图像,并返回一个模板列表及其名称的字典"""
templates = []
templates_id=[]
# print("list",os.listdir(template_folder))
#循环读取mb文件内的文件
for filename in os.listdir(template_folder):
# print("file",filename)
file_path = os.path.join(template_folder, filename)
#循环读取小文件夹内的内容
for filename in os.listdir(file_path):
img_path = os.path.join(file_path, filename)
# print("img",img_path)
img = cv2.imread(img_path, 0) # 读取为灰度图
# 使用文件名(不带扩展名)作为字典的键
key = os.path.splitext(filename)[0][0]
# print("key",key)
templates.append(img)
templates_id.append(key)
# print(templates)
return templates,templates_id
def multi_template_match(img, templates,templates_id):
"""在输入图像中执行多模板匹配,并返回匹配结果"""
results = []
for templ, name in zip(templates,templates_id):
# w, h = templ.shape[::-1]
res = cv2.matchTemplate(img, templ, cv2.TM_CCOEFF_NORMED)
# print("res",res)
threshold = 0.8 # 匹配阈值
loc = np.where(res >= threshold)
for i in zip(*loc[::-1]):
results.append(name)# 使用文件名作为结果的键
# print("result",results )
return results
if __name__=="__main__":
one()