想不想实现不触碰电脑屏幕,只是在空中拿着彩笔绘画,就可以把对应的颜色画到屏幕中去?

今天这个项目就可以帮助你实现该功能,只需要你会使用python,且有opencv和图像处理的基础知识就可以实现该项目了。

下面跟着我一起操作吧!

1.先熟悉什么是hsv图像:

①在 HSV 色彩空间中 H,S,V 这三个通道分别代表着色相(Hue),饱和度(Saturation)明度(Value)

②在 OpenCV 视觉库中,HSV 的数值被做了小的修改, H 的范围调整为 0~180,S 和 V 的范围为 0~255。

③通过控制hsv的阈值,就会在原图片上得到不同的图像。

2.在opencv上进行hsv操作:

import cv2image1=cv2.imread('puke.jfif')
image2=cv2.cvtColor(image1,cv2.COLOR_BGR2HSV)
cv2.imshow('ppp',image2)
cv2.waitKey(0)

就可以把图片变成hsv格式的:

3.我们尝试这,在上面加入createTrackba操作,可以通过设置hsv的值实现不是自己喜欢的颜色,让其消失,并让几张照片叠加在一起显示:

其代码如下:

import cv2
import numpy as np
'如果单纯地使用numpy的函数进行堆叠,对不同大小和不同通道的图像是无法进行堆叠的,所以我们需要自己实现一个堆叠方法,下面就是模板,可以实现我们想要的效果'
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]*rowshor_con = [imageBlank]*rowsfor 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 = horreturn verdef empty(a):passimage=cv2.imread('puke.jfif')
'============ 颜色检测(对想要的颜色进行检测)============='
cv2.namedWindow("TrackBars")  # 创建一个窗口
cv2.resizeWindow("TrackBars", 640, 240)  # 改变窗口的形状
cv2.createTrackbar("Hue Min", "TrackBars", 0, 180, empty)  # 绑定滑动条和窗口,定义滚动条的数值
cv2.createTrackbar("Hue Max", "TrackBars", 0, 255, empty)  # 第三个参数是默认值(打开图像的默认值),第四个参数是滑条的最大值
cv2.createTrackbar("Sat Min", "TrackBars", 0, 255, empty)
cv2.createTrackbar("Sat Max", "TrackBars", 0, 255, empty)
cv2.createTrackbar("Val Min", "TrackBars", 0, 255, empty)
cv2.createTrackbar("Val Max", "TrackBars", 0, 255, empty)while True:img = image# 色调(H)、饱和度(S)和明度(V)imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")  # 得到滑动条的数值h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")v_min = cv2.getTrackbarPos("Val Min", "TrackBars")v_max = cv2.getTrackbarPos("Val Max", "TrackBars")print(h_min, h_max, s_min, s_max, v_min, v_max)lower = np.array([h_min, s_min, v_min])upper = np.array([h_max, s_max, v_max])#lower指的是图像中低于这个lower的值,图像值变为0#upper指的是图像中高于这个upper的值,图像值变为0#而在lower~upper之间的值变成255#这样就是二值图像了mask = cv2.inRange(imgHSV, lower, upper)# 按位和进行计算imgResult = cv2.bitwise_and(img, img, mask=mask)#将图像叠加在一起imgStack = stackImages(0.6, ([img, imgHSV], [mask, imgResult]))cv2.imshow("Stacked Images", imgStack)cv2.waitKey(1)

当上述操作完成后,我们就可以通过启动摄像头,然后拿出自己的彩色笔,通过调制彩色笔,让中意的颜色,显示出来:

4.启动摄像头的代码:

cap = cv2.VideoCapture(0)
while True:success, img = cap.read()#左右镜像交换img = cv2.flip(img, 1)cv2.imshow("Result", img)if cv2.waitKey(1) & 0xFF == ord('q'):break

5.当启动摄像头后,把上述代码综合在一起运行

录制红色

显示绿色

其代码是:

import cv2
import numpy as np
'如果单纯地使用numpy的函数进行堆叠,对不同大小和不同通道的图像是无法进行堆叠的,所以我们需要自己实现一个堆叠方法,下面就是模板,可以实现我们想要的效果'
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]*rowshor_con = [imageBlank]*rowsfor 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 = horreturn verdef empty(a):passcap=cv2.VideoCapture(0)
'============ 颜色检测(对想要的颜色进行检测)============='
cv2.namedWindow("TrackBars")  # 创建一个窗口
cv2.resizeWindow("TrackBars", 640, 240)  # 改变窗口的形状
cv2.createTrackbar("Hue Min", "TrackBars", 0, 180, empty)  # 绑定滑动条和窗口,定义滚动条的数值
cv2.createTrackbar("Hue Max", "TrackBars", 0, 255, empty)  # 第三个参数是默认值(打开图像的默认值),第四个参数是滑条的最大值
cv2.createTrackbar("Sat Min", "TrackBars", 0, 255, empty)
cv2.createTrackbar("Sat Max", "TrackBars", 0, 255, empty)
cv2.createTrackbar("Val Min", "TrackBars", 0, 255, empty)
cv2.createTrackbar("Val Max", "TrackBars", 0, 255, empty)while True:success,image=cap.read()img = image# 色调(H)、饱和度(S)和明度(V)imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)h_min = cv2.getTrackbarPos("Hue Min", "TrackBars")  # 得到滑动条的数值h_max = cv2.getTrackbarPos("Hue Max", "TrackBars")s_min = cv2.getTrackbarPos("Sat Min", "TrackBars")s_max = cv2.getTrackbarPos("Sat Max", "TrackBars")v_min = cv2.getTrackbarPos("Val Min", "TrackBars")v_max = cv2.getTrackbarPos("Val Max", "TrackBars")print(h_min, h_max, s_min, s_max, v_min, v_max)lower = np.array([h_min, s_min, v_min])upper = np.array([h_max, s_max, v_max])#lower指的是图像中低于这个lower的值,图像值变为0#upper指的是图像中高于这个upper的值,图像值变为0#而在lower~upper之间的值变成255#这样就是二值图像了mask = cv2.inRange(imgHSV, lower, upper)# 按位和进行计算imgResult = cv2.bitwise_and(img, img, mask=mask)#将图像叠加在一起imgStack = stackImages(0.6, ([img, imgHSV], [mask, imgResult]))cv2.imshow("Stacked Images", imgStack)cv2.waitKey(1)

当上述操作都完成后,我们就可以记录自己调制的参数值,如代码:

#自己通过定义的hsv值进行设置
myColors = [[15,182,84,245,255,255],[112,104,133,255,255,255]]

6.接下来就是opencv常用的寻找轮廓,绘制轮廓,绘制矩形框,添加文本的常用操作

①先定义了一个寻找轮廓的函数,通过这个来返回一个坐标:

def getContours(img):#img是二值图像contours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)x,y,w,h = 0,0,0,0for cnt in contours:#轮廓的面积area = cv2.contourArea(cnt)if area>200:#cv2.drawContours(imgResult, cnt, -1, (255, 0, 0), 3)peri = cv2.arcLength(cnt,True)approx = cv2.approxPolyDP(cnt,0.02*peri,True)x, y, w, h = cv2.boundingRect(approx)return x+w//2,y

②然后定义一个寻找颜色的函数,通过这个函数就可以过滤出只剩我们想要颜色的视频,并通过索引将其rgb的值放入我们后续画的圈的参数中:

def findColor(img,myColors,myColorValues):#将图片转换成hsv格式imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)count = 0newPoints=[]for color in myColors:lower = np.array(color[0:3])upper = np.array(color[3:6])mask = cv2.inRange(imgHSV,lower,upper)#获取掩膜x,y=getContours(mask)#进行轮廓寻找cv2.circle(imgResult,(x,y),25,myColorValues[count],cv2.FILLED)if x!=0 and y!=0:newPoints.append([x,y,count])count +=1#cv2.imshow(str(color[0]),mask)if newPoints==[]:print('没有发现绘画笔')else:print(newPoints)return newPoints

③通过坐标点在图像上绘制带有颜色的实心圆圈:

def drawOnCanvas(myPoints,myColorValues):for point in myPoints:#对我们的点进行cv2.circle(imgResult, (point[0], point[1]), 25, myColorValues[point[2]], cv2.FILLED)

※※完成上述操作后,就可以实现整个项目的基本功能了,其效果如下:


整体效果

整个项目的代码如下:

import cv2
import numpy as np
#设置视频的宽和高
frameWidth = 1080
frameHeight = 640
cap = cv2.VideoCapture(0)
#改变视频的宽和高
cap.set(3, frameWidth)
cap.set(4, frameHeight)
#自己通过定义的hsv值进行设置
myColors = [[15,182,84,245,255,255],[112,104,133,255,255,255]]
#颜色的值
myColorValues = [[0,255,0],[147,20,255]]myPoints =  []  ## [x , y , colorId ]
#通过获取对应的轮廓,然后获得纵标,在坐标处标记,并将这个点的坐标存储
def findColor(img,myColors,myColorValues):#将图片转换成hsv格式imgHSV = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)count = 0newPoints=[]for color in myColors:lower = np.array(color[0:3])upper = np.array(color[3:6])mask = cv2.inRange(imgHSV,lower,upper)#获取掩膜x,y=getContours(mask)#进行轮廓寻找cv2.circle(imgResult,(x,y),25,myColorValues[count],cv2.FILLED)if x!=0 and y!=0:newPoints.append([x,y,count])count +=1#cv2.imshow(str(color[0]),mask)if newPoints==[]:print('没有发现绘画笔')else:print(newPoints)return newPoints
#通过寻找轮廓,然后返回最小轮廓处理后的坐标值
def getContours(img):#img是二值图像contours,hierarchy = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)x,y,w,h = 0,0,0,0for cnt in contours:#轮廓的面积area = cv2.contourArea(cnt)if area>200:#cv2.drawContours(imgResult, cnt, -1, (255, 0, 0), 3)peri = cv2.arcLength(cnt,True)approx = cv2.approxPolyDP(cnt,0.02*peri,True)x, y, w, h = cv2.boundingRect(approx)return x+w//2,y
#对我们存储的点按照我们的颜色表进行标记
def drawOnCanvas(myPoints,myColorValues):for point in myPoints:#对我们的点进行cv2.circle(imgResult, (point[0], point[1]), 25, myColorValues[point[2]], cv2.FILLED)while True:success, img = cap.read()#左右镜像交换img = cv2.flip(img, 1)imgResult = img.copy()newPoints = findColor(img, myColors,myColorValues)#将标记的点放入列表中if len(newPoints)!=0:for newP in newPoints:myPoints.append(newP)#对相应的点输入进我们上面定义好的函数if len(myPoints)!=0:drawOnCanvas(myPoints,myColorValues)cv2.imshow("Result", imgResult)if cv2.waitKey(1) & 0xFF == ord('q'):break

仅供学习参考,如有不足,敬请指正!

opencv项目6----AI绘画(隔空绘画)相关推荐

  1. 基于Opencv实现的多彩隔空画图

    1.问题概述 人工智能带火了计算机视觉的人才需求,作为计算机视觉应用开发框架OpenCV也越来越受到欢迎,市场需求大增.因此,在学习Python的基础上,进行Opencv技术的学习是十分重要且有必要的 ...

  2. 隔空作画,握拳清屏,这个手部跟踪项目火了,在线可玩

    在屏幕上隔空作画是近来新兴的一种有趣应用,其中涉及复杂的手部跟踪技术,这类技术成熟之后可用于提升应用程序的交互体验.此前机器之心曾报道过可以隔空写字.绘图的有趣项目「air-drawing」,该项目利 ...

  3. 只有大规模算力才能救AI?强化学习之父 vs 牛津教授掀起隔空论战

    乾明 安妮 发自 凹非寺 量子位 出品 | 公众号 QbitAI 70年来, 人们在AI领域"一直连续犯着同样的错误". 这是"强化学习之父"理查德·萨顿(Ri ...

  4. 手机扫一扫,现实物体隔空「复制粘贴」进电脑!北大校友的AI新研究,现在变成AR酷炫应用...

    十三  白交 发自 凹非寺 量子位 报道 | 公众号 QbitAI 魔法变现实,酷炫又实用. 还记得两年前,Zach King(男巫)的爆红魔术吗? 不仅从纸直接蹦出一个手机,还直接扔进了电脑里形成虚 ...

  5. 电脑复制粘贴_手机扫一扫,现实物体隔空复制粘贴进电脑!北大校友的AI新研究,现在变成AR酷炫应用...

    本文经AI新媒体量子位(ID:QbitAI)授权转载,转载请联系出处 十三  白交 发自 凹非寺 魔法变现实,酷炫又实用. 还记得两年前,Zach King(男巫)的爆红魔术吗? 不仅从纸直接蹦出一个 ...

  6. 下一个爆款AI应用?视频交互新方式——AR隔空书写的应用探索和实践

    作者:末土 阿里云视频云视觉算法团队 节日祝福 什么是AR隔空书写?如上图所示,我们通过手势识别算法识别出手指关键点的轨迹,同时判断用户的手处于落笔/抬笔的状态,然后根据这些信息把用户写的内容渲染在视 ...

  7. 乔丹LeCun李开复隔空对话:我们对智能一无所知;AI研究的12大趋势

    夏乙 允中 假装发自 国会 量子位 出品 | 公众号 QbitAI "我们还没造出智能,也不知道智能是什么." "机器要想像人类.动物一样智能,需要先获得大量知识.&qu ...

  8. AI可以自动生成绘画吗?分享几款AI绘画软件

    AI绘画热潮来临之前,我在网上看到不少人发了AI绘画的图片,除了画人物,还有画漫画和风景的图片,画面真实和色彩丰富程度让我不敢相信是AI画的,于是就去网上搜索AI可以自动生成绘画吗?在搜索的过程中,我 ...

  9. 让创意更自由流畅,ai输入文字生成绘画软件推荐

    随着人工智能技术的不断发展和应用,人工智能技术的应用正在不断改变着我们的生活和创作方式.这种技术允许我们通过输入文字描述,自动生成对应的图像作品,提高了图像设计和艺术创作的效率.ai输入文字生成绘画不 ...

  10. OpenAI CEO亮相“AI春晚”,与张宏江隔空问答:10年内会有超强AI

    <AI未来指北>栏目由腾讯新闻推出,邀约全球业内专家.创业者.投资人,探讨AI领域的技术发展.商业模式.应用场景.及治理挑战. 文 / 腾讯科技 苏扬 .郝博阳 凭借ChatGPT走红的O ...

最新文章

  1. Java 内存分配——Thinking in Java 4th 读书笔记
  2. 手把手教你用 TensorFlow 实现文本分类(下)
  3. 利用 Selenium 自动化 web 测试【步骤详解】
  4. 和煤一样的黑色矿石_煤精?黑琥珀?煤球一样的东西这么值钱!
  5. (转)Linux环境变量的设置和查看方法
  6. LeetCode 231. 2的幂
  7. 浏览器窗口尺寸clientHeight / scrollHeight / offsetHeight / innerHeight
  8. Lambda 表达式详解~简化匿名内部类
  9. Mask R-CNN官方实现“又”来了!基于PyTorch,训练速度是原来2倍
  10. POJ 2240 Arbitrage Bellman_ford 判读是否存在正环
  11. 让DB2跑得更快——DB2内部解析与性能优化
  12. 番外篇:R or Python,到底学哪个?这篇文章来告诉你......
  13. How to Root Nexus 5 on Android 4.4.4 KTU84P and Install CWM Recovery
  14. vue 多个组件动态加载(动态组件的使用)
  15. 中国首个证券纠纷示范判决机制的规定在沪发布
  16. 小米蓝牙键盘怎么连接_小米2手机连接使用蓝牙键盘和蓝牙鼠标教程(原创)
  17. android系统移植之按键驱动篇
  18. 计算机专业要学英语口语,学习英语口语必须掌握两大法宝
  19. Python一亿以内的素数个数_Python编程100例(上)
  20. 部分和 前缀和 二维前缀和

热门文章

  1. 保存Simulink仿真模型为图片及PDF
  2. HI3559A,Hi3519A,Hi3556A芯片产品参数介绍资料
  3. MySQL的索引与事务(面试必考) - 细节狂魔
  4. VelocityTracker 使用
  5. 简单易学的机器学习算法——Mean Shift聚类算法
  6. 51开发板的功能及简单使用
  7. git报错:fatal: unable to access ‘...‘: Failed to connect to github port 443: Timed out
  8. nps内网穿透p2p隧道实战
  9. MDClub 轻量级网论坛源码
  10. 计算机网络——循环冗余校验码