昨天有点意思同学和我讨论问题了,问题还都挺好的,咱两陆陆续续讨论了还是蛮多的。
还有很多,懒得发了,通过讨论,问题基本上都已经解决了,本来懒得写了,觉得太花时间了,想了想决定还是写吧,别问为啥,问就是热爱编程,乐于助人。
好了,吹牛到此为止了。
问题一&问题二:自动截图,图像变换
主要就是对图片数据做切片操作,数据修改等。
对于电脑来说,不论文字,图片,还是视频,都是数据。
如果给一串数字,反过来也可以得到图片。
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
data = np.linspace(0,255,27,dtype=np.uint8).reshape(3,3,3)
print(data)
plt.imshow(data)
plt.show()
对数据进行切片,对应的图片也会变化。
代码语言:javascript复制import numpy as np
import matplotlib.pyplot as plt
data = np.linspace(0,255,27,dtype=np.uint8).reshape(3,3,3)
new_data = data[0:2,:,:]
plt.imshow(new_data)
plt.show()
了解了以上的内容后,下面就可以进一步学习opencv是如何对图片数据进行操作的(numpy切片),为了更好的观察图片变化。我用程序将1-9的数字图片组合到一起了,同时给每张图片加了边框。
其中一张是没有重复数字,另外一张是有随机的重复数字的。
上面的两张图片,宽和高分别为180,对应每张小图片宽和高为60。
显示第一行的3个数字。
代码语言:javascript复制import cv2
img = cv2.imread("num_img.jpg")
cv2.imshow("img",img)
img_123 = img[0:60]
cv2.imshow("img123",img_123)
cv2.waitKey(0)
显示数字2
代码语言:javascript复制
import cv2
img = cv2.imread("num_img.jpg")
cv2.imshow("img",img)
img_123 = img[0:60]
cv2.imshow("img123",img_123)
img_123_2 = img[0:60,60:120]
cv2.imshow("img123_2",img_123_2)
cv2.waitKey(0)
准备三张图片,修改图片数据。
代码语言:javascript复制import cv2
apple = cv2.resize(cv2.imread("apple.png"),(60,60))
watermalon = cv2.resize(cv2.imread("watermalon.png"),(60,60))
orange = cv2.resize(cv2.imread("orange.png"),(60,60))
img = cv2.imread("num_img.jpg")
cv2.imshow("img",img)
img[0:60,60:120] = apple
img[60:120,120:180] = watermalon
img[120:180,60:120] = orange
cv2.imshow("img2",img)
cv2.waitKey(0)
问题3&问题4:不规则物体检测与多个目标检测
不规则物体检测这里就不讨论了,多个目标检测,不用最大值最小值,将找到的所有情况筛查一遍即可。
查找图片上的数字3,并替换成苹果。
可是3有很多个,如何将所有的3都找出来呢?
不用最大值最小值,直接返回找到的所有结果,设置阈值。
看上去好像没问题,找到4个3,但是打印count的数字会发现,已经有16个了。
之所以会出现这种情况,是因为出现了冗余检测,模板匹配的原理是滑动匹配的,所以图片偏移一点点还是算检测到。
我这里的图片3与大图中的3是一模一样的,所以这里可以继续调整阈值threshold为0.99。这样可以实现刚好找到4个。
标记上数字编号效果。
不过有些图片,匹配的图形与原图并非一模一样,总是有点细小区别。比如我这里圆形,看上去非常相似,其实每个圆形还是有些细小区别的。导致很多图形被多次匹配。
要解决这个问题,具体可看这篇文章:
https://www.cnblogs.com/makefile/p/nms.html,进行非极大值抑制,去除那些重复的。
但是上面的方法也只能针对哪些模板与原图方向比较一致的效果才比较好。如果方向不一致的,阈值就比较难调整,太大误检测比较多,太小很多未检测到。
要鲁棒性更强,需要训练模型识别了,然后配合图片特征点,自动拉正,效果就会比较好了。类似人脸检测一样,人脸倒着就检测不出来,通过特征点,把人脸正过来就可以检测了。
完整代码:
阈值需要更加自己的实际情况调整。
代码语言:javascript复制import cv2
import numpy as np
def py_nms(dets, thresh):
"""Pure Python NMS baseline."""
# x1、y1、x2、y2、以及score赋值
# (x1、y1)(x2、y2)为box的左上和右下角标
x1 = dets[:, 0]
y1 = dets[:, 1]
x2 = dets[:, 2]
y2 = dets[:, 3]
scores = dets[:, 4]
# 每一个候选框的面积
areas = (x2 - x1 1) * (y2 - y1 1)
# order是按照score降序排序的
order = scores.argsort()[::-1]
# print("order:",order)
keep = []
while order.size > 0:
i = order[0]
keep.append(i)
# 计算当前概率最大矩形框与其他矩形框的相交框的坐标,会用到numpy的broadcast机制,得到的是向量
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
# 计算相交框的面积,注意矩形框不相交时w或h算出来会是负数,用0代替
w = np.maximum(0.0, xx2 - xx1 1)
h = np.maximum(0.0, yy2 - yy1 1)
inter = w * h
# 计算重叠度IOU:重叠面积/(面积1 面积2-重叠面积)
ovr = inter / (areas[i] areas[order[1:]] - inter)
# 找到重叠度不高于阈值的矩形框索引
inds = np.where(ovr <= thresh)[0]
# print("inds:",inds)
# 将order序列更新,由于前面得到的矩形框索引要比矩形框在原order序列中的索引小1,所以要把这个1加回来
order = order[inds 1]
return keep
# 加载图片
tpl = cv2.imread("circle2.png")
target = cv2.imread("2.png")
h, w = tpl.shape[:2] # 获取模板图像的高宽
apple = cv2.resize(cv2.imread("apple.png"),(h,w))
method = cv2.TM_CCOEFF_NORMED # 标准相关匹配算法
# 开始匹配
result = cv2.matchTemplate(target, tpl, method)
threshold = 0.9
# 取匹配程度大于�的坐标
loc = np.where(result >= threshold)
# 大于模板阈值的目标置信度 一维数据
score = result[result >= threshold]
# 将模板数据坐标进行处理成左上角、右下角的格式
x1 = loc[1].reshape(-1, 1) # 变成n行1列维度
x2 = (loc[1] w).reshape(-1, 1) # 变成n行1列维度
y1 = loc[0].reshape(-1, 1) # 变成n行1列维度
y2 = (loc[0] h).reshape(-1, 1) # 变成n行1列维度
score = score.reshape(-1, 1) # 变成n行1列维度
# 拼接数据 水平
data_hstack = np.hstack((x1,y1,x2,y2,score))
print(data_hstack)
# 极大值抑制 返回对应的索引值
keep = py_nms(data_hstack,0.3)
print(keep,len(keep))
# 取出索引对应的矩形框
dets = data_hstack[keep]
print(dets,len(dets))
count = 0
for det in dets:
count = 1
cv2.rectangle(target, (int(det[0]), int(det[1])), (int(det[2]), int(det[3])), (0, 0, 255), 2)
cv2.putText(target, str(count), (int(det[0]) w//4, int(det[1]) h*3//4), 3, 1.2, (255, 0, 0), 2)
cv2.imshow('result', target)
cv2.waitKey(0)