本次作业内容:
输出图片的信息,(行 列 通道等),使用滑动条完成两张图片的图像混合过渡,并在图中用红色矩形圈出足球目标(改变像素值)
分四步走
1. 输出图片的信息
使用img.shape
方法即可
代码如下所示
# 初始化一些信息
img1_path = './img/sc.jpeg'
img2_path = './img/openCV_LOGO.jpg'
...
...
...
# img1_SIZE = 1680 * 1050
# img2_SIZE = 435 * 384
img1_Size = (1680, 1050) # 设置图像大小
img2_Size = (435, 384) # 设置图像大小
img1 = cv2.imread(img1_path)
img2 = cv2.imread(img2_path)
img3 = img1.copy()
img_original = cv2.imread(img1_path)
print("img1图像信息:", end='')
print(img1.shape)
print("img2图像信息:", end='')
print(img2.shape)
print("img3图像信息:", end='')
print(img3.shape)
2. 制作一个滑动条
使用cv2.createTrackbar(trackbarName, windowName, value, count, onChange)
方法即可
代码如下:
MyTrackBarName = 'Blending Weight'
window_Name = 'image'
...
...
...
# 创建滑动条
cv2.createTrackbar(MyTrackBarName, window_Name, 0, 100, nothing) # 设置滑动条来完成两张图片的混合过渡
像这样:
3. 完成两张图片的图像混合过渡
这里就需要将图片抠出来,然后放置到足球图片上去
结果像这样:
是这两张图片
和
这不就是抠图嘛~
OpenCV中可以对图像进行按位运算,在OpenCV中,黑色,也就是(0)相当于透明,可以被任何其他的东西替换,学过ps的同学应该知道,图像如果低是透明的,就可以很轻松的与其他的图片叠加在一起,谁在上谁在下,要调整的不过就是图层而已。
跑题了,在OpenCV中抠上面的logo图我们可以分成以下步骤:
- 将背景图的指定区域(你要放置的地方)这里的区域要与OpenCV的logo图片大小(像素值)一致
- 我们需要先将OpenCV的logo转换成灰度图,好进行下一步处理
- 将灰度图二值化,也就是非黑及白。(制作蒙版)
- 再将其黑白颠倒,同时将彩色的logo放到蒙版上去
- 将这个扣好的图片放到背景图上去。
- 我们一步步来
- 将背景图的指定区域(你要放置的地方)复制出来
注:这里的区域要与OpenCV的logo图片大小(像素值)一致
代码如下:
roi = img1[0:rows, 0:columns] # 截取img1(足球照)中左上角与img2相同大小的图片,赋值给roi
- 我们需要先将OpenCV的logo转换成灰度图,好进行下一步处理
代码如下:
img2_Gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY) # 将logo转换为灰度图
- 将灰度图二值化,也就是非黑及白。(制作蒙版)
ret, mask = cv2.threshold(img2_Gray, 200, 255, cv2.THRESH_BINARY) # 将灰度图二值化,以制作MASK
# bitwise_and是对二进制数据进行“与”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“与”操作,1&1=1,1&0=0,0&1=0,0&0=0
# bitwise_or是对二进制数据进行“或”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“或”操作,1|1=1,1|0=0,0|1=0,0|0=0
# bitwise_xor是对二进制数据进行“异或”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“异或”操作,1^1=0,1^0=1,0^1=1,0^0=0
# bitwise_not是对二进制数据进行“非”操作,即对图像(灰度图像或彩色图像均可)每个像素值进行二进制“非”操作,~1=0,~0=1
- 再将其黑白颠倒,同时将彩色的logo放到蒙版上去
mask_inv = cv2.bitwise_not(mask) # 进行二进制"非"操作,将mask颜色反转,以确保我们要的图形不是黑色(0),不要的图形都是黑色(0)
# 方便进行下一步“与”操作。
- 将这个扣好的图片放到背景图上去。
img1_BG = cv2.bitwise_and(roi, roi, mask=mask) # roi 和 mask进行 “与” 操作,取 roi 中与 mask 中不为 0(黑色)的值对应的像素的值,
# 其他值为 0 ,放入img_BG中。
# 注意这里必须有 mask = mask 或者 mask = mask_inv, 其中的 mask = 不能忽略
# 这里取出来一个黑色的遮罩(0),方便后面将我们要扣的图像放入遮罩中
img2_FG = cv2.bitwise_and(img2, img2, mask=mask_inv) # 将 “OPENCV_LOGO” 的原图放入遮罩中,剔除掉遮罩外的内容,遮罩外为黑色(0)
# 这样提取出来的图像就是彩色的原图,如果进行抗锯齿等处理就更完美了。
dst = cv2.add(img1_BG, img2_FG) # 将扣好的图片与裁切好的足球照片(img1)放在一起,准备放入足球照片中去。
- 放进足球照片(img1)中去,完成抠图。
img3[0:rows, 0:columns] = dst # 放进足球照片(img1)中去,完成抠图。
4. 在图中用红色矩形圈出足球目标(改变像素值)
这里还没有做到智能获取,是手动获取的像素点。
代码如下:
football = img_original[897:1044, 1270:1400] # 先复制一下足球区域的各个像素
# 这里注意!!! 不知道为什么,这个变量并没有存储这些像素值,而是仅仅标记了一下
# 所以需要先复制一份原始图像,标记原始图像,然后再粘贴上去。
img3[887:1054, 1260:1410] = (0, 0, 255) # 将足球区域变成红色
img3[897:1044, 1270:1400] = football # 将足球粘贴回去
5. 收尾,完成使用滑动条从透明到不透明显示
代码如下:
...
...
...
def img_blending(wdName, trackBarName, image1, image2, ):
weight_x: float = (100 - cv2.getTrackbarPos(trackBarName, wdName)) / 100 # 动态获取滑动条的值并转换成小数
weight_y: float = 1 - weight_x # 另一个权值为 1 - weight_x
return cv2.addWeighted(image1, weight_x, image2, weight_y, 0) # 返回对象
while 1:
cv2.imshow(window_Name, img_blending(window_Name, MyTrackBarName, img_original, img3)) # 显示主窗口
k = cv2.waitKey(1) & 0xFF # 按 “ESC” 退出
if k == 27:
break
cv2.destroyAllWindows()
最终效果图:
本次作业到这里就完成了