失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > python+opencv多进程实现识别魔方颜色 通过kociemba算法得出算法字符串并画图(附毕

python+opencv多进程实现识别魔方颜色 通过kociemba算法得出算法字符串并画图(附毕

时间:2019-08-14 06:22:51

相关推荐

python+opencv多进程实现识别魔方颜色 通过kociemba算法得出算法字符串并画图(附毕

完整毕设成果视频如下:

本科毕业设计转魔方(声音略大)

python+opencv本科毕业设计转魔方(声音略大)

上一篇博客已经给大家讲了鼠标hsv获取魔方颜色阈值方法,具体见python+opencv 识别魔方照片块颜色并可鼠标获取目标区域hsv值

本次给大家讲讲识别的整套流程(其实是从github上扒下来的),看了一个寒假改了改,改成自己能用的,单进程运算六个面按照他的方法识别其实挺慢的,于是便做了一些改进用了多进程(进程池)的方法,创建六个进程,每个进程分别处理一个面,这样就快多了,原来需要三十秒左右,现在好的时候能到一两秒内,分享出来给大家共享。

先呈现一下效果图:

`d 可以看出,快的时候将近一秒,具体要看cpu了。(注:第一次刚一开始运行的时候会很慢,如果时间很长都没有出结果把它关掉,重新在运行一遍就好啦!)

关于多进程进程池的问题,前段时间冥思苦想,一开始用多线程思路,使用threading模块,具体网上都有参考例子,可以搜一下,例如:/tyomcat/p/5486827.html,但是用多线程后出现一个致命问题,并不是想自己想的那样更快,反而慢了,原因应该是网上说的 GIL全局锁,在解释器解释执行 Python 代码时,先要得到这把锁,意味着,任何时候只可能有一个线程在执行代码,其它线程要想获得 CPU 执行代码指令,就必须先获得这把锁,如果锁被其它线程占用了,那么该线程就只能等待,直到占有该锁的线程释放锁才有执行代码指令的可能。

因此,这也就是为什么两个线程一起执行反而更加慢的原因,因为同一时刻,只有一个线程在运行,其它线程只能等待,即使是多核CPU,也没办法让多个线程「并行」地同时执行代码,只能是交替执行,因为多线程涉及到上下文切换、锁机制处理(获取锁,释放锁等),所以,多线程执行不快反慢。

在python里,如果想更多的利用多核cpu内存,还是更多利用多进程处理比较好。

/topleeyap/article/details/78981848这篇博客里有具体的实现多进程的几种方式,我用的是进程池的方式(Pool):

ps=Pool(6)#cpu=ps.apply(colorMatch,args=(i,))# 同步执行up_cpu=ps.apply_async(colorMatch,args=('up',)) # 异步执行right_cpu=ps.apply_async(colorMatch,args=('right',)) front_cpu=ps.apply_async(colorMatch,args=('front',)) down_cpu=ps.apply_async(colorMatch,args=('down',)) left_cpu=ps.apply_async(colorMatch,args=('left',)) back_cpu=ps.apply_async(colorMatch,args=('back',)) # 关闭进程池,停止接受其它进程ps.close() # 阻塞进程ps.join()

我创建了六个进程:up_cpu、right_cpu、front_cpu、down_cpu、left_cpu、back_cpu

将拍摄的六个面照片依次传入颜色识别函数colorMatch(side):

def colorMatch(side):cube_rgb = cv2.imread( side + '.jpg')

这套颜色识别方法,是对六种颜色分别计算出掩膜,将其加和后对整个面进行识别,

mask = red_erosion + green_erosion + yellow_erosion + blue_erosion + orange_erosion + white_erosionmask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel_50)#开运算分割色块mask = cv2.erode(mask, kernel_50, iterations = 1)res = cv2.bitwise_and(cube_hsv, cube_hsv, mask = mask)

并且通过开运算和腐蚀函数对图像进行色块分离:

效果图如下:(分别是第一个mask,第二个mask,第三个mask,第四个res图)

可以看出,随着处理,色块分离越来越明显。

中点色块颜色及坐标def midpoint(x1,y1,x2,y2):x_mid = int((x1 + x2)/2)y_mid = h - int(((y1 + y2)/2))color = res[y_mid, x_mid]return ([int(color[0]), int(color[1]), int(color[2])])

此处函数为识别每个面hsv图中九个色块的中点颜色和坐标,供后面使用

# midpoint获得每个面九个色块的颜色mid_1 = midpoint(x_min, y_max, (x_min + int(width/3)), (y_max - int(height/3)))mid_2 = midpoint((x_min + int(width/3)), y_max, (x_min + int(width*2/3)), (y_max - int(height/3)))mid_3 = midpoint((x_min + int(width*2/3)), y_max, x_max, (y_max - int(height/3)))mid_4 = midpoint(x_min, (y_max - int(height/3)), (x_min + int(width/3)), (y_max - int(height*2/3)))mid_5 = midpoint((x_min + int(width/3)), (y_max - int(height/3)), (x_min + int(width*2/3)), (y_max - int(height*2/3)))mid_6 = midpoint((x_min + int(width*2/3)), (y_max - int(height/3)), x_max, (y_max - int(height*2/3)))mid_7 = midpoint(x_min, (y_max - int(height*2/3)), (x_min + int(width/3)), y_min)mid_8 = midpoint(x_min + int(width/3), (y_max - int(height*2/3)), (x_min + int(width*2/3)), y_min)mid_9 = midpoint(x_min + int(width*2/3), (y_max - int(height*2/3)), x_max, y_min)mids = [mid_1, mid_2, mid_3, mid_4, mid_5, mid_6, mid_7, mid_8, mid_9]

这是获得九个色块的颜色保存在mids列表中

s=''for rgb in mids:#hsvif ((0<=rgb[0]<=180 ) and (0<=rgb[1]<=50 ) and( 201<=rgb[2]<=255)):#白s+='D'elif ((3<=rgb[0]<=9 )and (115<=rgb[1]<=190 )and (195<=rgb[2] <=255)):#澄s+='B'elif ((95<=rgb[0] <=124) and (123<=rgb[1]<=253) and (109<=rgb[2]<=240)):#蓝s+='L'elif( (68<=rgb[0]<=82) and (140<=rgb[1]<=255) and (120<=rgb[2]<=245)):#绿s+='R'elif ((20<=rgb[0]<=34) and (125<=rgb[1]<=243) and(142 <=rgb[2]<=255)):#黄s+='U'elif ((170<=rgb[0]<=182)and (110<=rgb[1] <=240 )and (145<=rgb[2]<=255 )):#红s+='F'return(s)

此功能为将各种点色块hsv转化为字符串供给kociemba算法得到解法

注意主函数里

#cpu=ps.apply(colorMatch,args=(i,))# 同步执行up_cpu=ps.apply_async(colorMatch,args=('up',)) # 异步执行

注释的是同步执行,后面的是异步执行操作

通过kociemba.solve(get_str)函数就能直接得到kociemba算法还原魔方的字符串了

Tip:

这里有一个小细节,为了让操作员更能清楚的知道识别的颜色对不对,我画了一个draw窗口来显示魔方展开后的颜色样子:

这个本来想通过多线程来画图,原本想的是六个进程每识别完一个面就能在draw画布画出相应的色块,结果试验后发现我以为的多进程共用参数draw,实际上是调用了六次,并没有实现在同一个画布上画图功能。

冥思苦想想了两天,由一开始从网上查资料开辟共享内存或者Manager方法来实现,结果通通不行,突然想到可以把识别颜色后给出的字符串来转换为对应的颜色:

展示一部分自己写的colordraw .py文件里面开头部分,将字符串转换为对应颜色的画图程序:

def drawcolor(get_str):#URFDLB 传入54个字符 #strcolor={'U':(0,255,255),'R':(0,255,0),'F':(0,0,255),'D':(255,255,255),'L':(255,191,0),'B':(0,128,255)} #strcolor="URFDLB" draw_str=[]#BGR:U=(0,255,255)R=(0,255,0)F=(0,0,255)D=(255,255,255)L=(255,191,0)B=(0,128,255) for key in get_str:#遍历54个字符中每个字符,i为字符

`

一开始想用字典,把每个字符对应的颜色输进去,结果实际调用的时候发现总是没法一起调用,思考了两天两夜才想到用这个for循环+列表就可以实现了,因为54个块的位置是固定的,所以可以把字符串每个字符依次填入到对应的色块中去,然后去寻找他所对应的颜色就ok啦!

辛辛苦苦写了这么多,希望能对大家应用有些启发~~~~

有什么建议可以在下方评论哦,具体程序见:

链接:python+opencv识别魔方颜色+kociemba算法应用+显示识别效果

python+opencv多进程实现识别魔方颜色 通过kociemba算法得出算法字符串并画图(附毕设完整视频)

如果觉得《python+opencv多进程实现识别魔方颜色 通过kociemba算法得出算法字符串并画图(附毕》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。