在 计算机视觉识别新增物品笔记 一 https://blog.csdn.net/phker/article/details/107830114 之后
又对其进行了改进,
总体思路如下:
1.先将图片图像二值化,方便后面进行计算。
2.新图减去背景图 消除背景,
3.图像形态学中的腐蚀和膨胀 消除噪点。
4.然后是蒙布消除背景图片中的其它内容 达到抠图的功能。
效果如下图(为防止遗漏其它像素, 我扣的边距比较大。因为后面还有二次处理,尽量不要丢失信息。)
# 提取图片中新增部分第二版
# 总体思路,
# 先将图片图像二值化,方便后面进行计算。
# 新图减去背景图 消除背景,
# 图像形态学中的腐蚀和膨胀 消除噪点。
# 然后是蒙布消除背景图片中的其它内容 达到抠图的功能。
import numpy as np
import matplotlib.image as mpimg # mpimg 用于读取图片
import matplotlib.pyplot as plt # plt 用于显示图片
#import MyOpenCV as mycv
import cv2
beijingtu = cv2.imread('beijingtu.jpg') # 背景图 读取和代码处于同一目录下的
yaoshiYuanTu = cv2.imread('yaoshitu.jpg') # 钥匙图
#三通道变成了一通道
#beijingtu = cv2.rgb2gray(beijingtu)
#yaoshitu = cv2.rgb2gray(yaoshitu)
beijingtu=cv2.cvtColor(beijingtu,cv2.COLOR_BGR2GRAY)#将其转换为灰度图,为进一步二值化
yaoshitu=cv2.cvtColor(yaoshiYuanTu,cv2.COLOR_BGR2GRAY)#将其转换为灰度图,为进一步二值化
#锐化,取整数,二值化,方便求物体范围
#yaoshitu = np.round(yaoshitu,decimals=-1)#精确到10位,相当于锐化了
#beijingtu = np.round(beijingtu,decimals=-1)#精确到10位,相当于锐化了
#ret,yaoshitu=cv2.threshold(yaoshitu,125,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)#采用OTSU自适应阈值,关于OTSU算法网络资源较多
ret,yaoshituBool=cv2.threshold(yaoshitu,70,255,cv2.THRESH_BINARY_INV)
ret,beijingtuBool=cv2.threshold(beijingtu,70,255,cv2.THRESH_BINARY_INV)#采用OTSU自适应阈值,关于OTSU算法网络资源较多
# plt.imshow(yaoshitu,'gray') # 显示图片
# plt.axis('off') # 不显示坐标轴
# plt.show()
# plt.imshow(beijingtu,'gray') # 显示图片
# plt.axis('off') # 不显示坐标轴
# plt.show()
#第一步:去掉背景图片
newtu = yaoshituBool - beijingtuBool #减去125 再去掉
# plt.imshow(newtu,'gray') # 显示图片
# plt.axis('off') # 不显示坐标轴
# plt.show()
#第二步 消除背景中的噪点
#图像形态学,开运算 是先腐蚀在膨胀,用来消除背景中的噪点
#下面是一些图像处理中形态学的知识
# 开运算:先腐蚀再膨胀,用来消除小物体
# 闭运算:先膨胀再腐蚀,用于排除小型黑洞
# 形态学梯度:就是膨胀图与俯视图之差,用于保留物体的边缘轮廓。
# 顶帽:原图像与开运算图之差,用于分离比邻近点亮一些的斑块。
# 黑帽:闭运算与原图像之差,用于分离比邻近点暗一些的斑块。
element = cv2.getStructuringElement(cv2.MORPH_OPEN,(10,10))
newtu2 = cv2.morphologyEx(newtu, cv2.MORPH_OPEN, element)
element = cv2.getStructuringElement(cv2.MORPH_DILATE,(200,200))
newtu2 = cv2.morphologyEx(newtu2, cv2.MORPH_DILATE, element) #再膨胀一些,方便截图
#抠图 去掉背景后的图片 方法一 有点慢
#QuBeiJingTu = newtu2 * yaoshitu # / 255
#print(yaoshitu.shape)
# yaoshiYuanTu = cv2.imread('yaoshitu.jpg') # 钥匙图
# height = yaoshiYuanTu.shape[0] #将tuple中的元素取出,赋值给height,width,channels
# width = yaoshiYuanTu.shape[1]
# #print("height:%s,width:%s,channels:%s" % (height,width,channels))
# print(yaoshiYuanTu.size) #打印图像数组内总的元素数目(总数=高X宽X通道数)
# for row in range(height): #遍历每一行
# for col in range(width): #遍历每一列
# #for channel in range(channels): #遍历每个通道(三个通道分别是BGR)
# if newtu2[row][col] == 255:
# pass
# # yaoshiYuanTu[row][col][0] = yaoshiYuanTu[row][col][0]
# # yaoshiYuanTu[row][col][1] = yaoshiYuanTu[row][col][1]
# # yaoshiYuanTu[row][col][2] = yaoshiYuanTu[row][col][2]
# else:
# yaoshiYuanTu[row][col][0] = 255
# yaoshiYuanTu[row][col][1] = 255
# yaoshiYuanTu[row][col][2] = 255
# #通过数组索引访问该元素,并作出处理
#yaoshiYuanTu = cv2.imread('yaoshitu.jpg') # 钥匙图
#抠图 去掉背景后的图片 方法二
yaoshiYuanTu[newtu2 < 200] = 255
#np.where(yaoshiYuanTu[ newtu2 > 200])
# #newtu[newtu>150]=255
# #mpimg.imsave("D:\\newtu.jpg",newtu)
plt.imshow(yaoshiYuanTu) # 显示图片
plt.axis('off') # 不显示坐标轴
plt.show()
此方法中采用的仍然是经典的图像处理算法。
虽然够用了。 但在抠出物品边缘细节的能力上,还有些欠缺。
如果想更好的解决此问题还需要加入物品边缘算法,
计划考虑使用多层神经元,具体无法口述,有点类似神经元的算法。 但是里面并不需要学习和梯度下降。
如果工作需要,打算再写第三版。