OpenCV确定哪两个色调值最能代表图像

2024-04-20 08:30:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我想确定在python3脚本中使用OpenCV最能代表图像的2个色调值。 到目前为止,我已经能够访问色调通道并显示其色调直方图: enter image description here

如你所见,基本上有两种不同色调的像素,米色和绿色。在

我已获得色调频道的访问权,如下所示:

hsv = cv.cvtColor( self.img, cv.COLOR_BGR2HSV ) hue,sat,val = cv.split(hsv)

在色调通道上操作以确定哪两个色调值最能代表图像的最有效方法是什么?在

请求编辑#1个原始图像: enter image description here

编辑2就快到了,但仍需要帮助:

我拼凑了一些代码来使用OpenCV kmeans将图像转换为2种颜色:

仍然需要:

  1. 我真的不想转换回uint8,并使原始图像为2种颜色。我想知道这两种颜色的色调值。如何从kmeans输出参数中获取这两个值?在
  2. 有没有一种方法可以减少使用kmeans进行转换的时间?kmeans在我的Raspberry PiZero上使用Python3脚本将其转换为2种颜色需要8.6秒。在Gimp中转换为2种颜色几乎是瞬间的(我知道这是不同的处理器,但8.6秒的Pi-Zero对我来说是不可用的,也许1秒就可以了)。我只是一个新手,但在我看来,这个kmeans代码是作用于所有的RGB像素,当我只想对色调的行为,所以我不能让kmeans只对色调和削减时间相当大(这样做有点超出我的能力在这一点上)。在

以下是耗时8.6秒的3.JPG图像: enter image description here


Tags: 方法代码图像脚本编辑时间代表像素
1条回答
网友
1楼 · 发布于 2024-04-20 08:30:02

我已经解决了你在帖子中提到的一些事情。在

  1. 你不应该回到uint8。中心是一个大小(2,3)的数组,其中行是中心点(即色调),列是每个色调的BGR值。

  2. 我已经切换到scipykmeans2,而不是使用OpenCVs实现。在同一张图片上它似乎比OpenCV快3倍。在

    import numpy as np
    from scipy.cluster.vq import kmeans, kmeans2
    import time, sys, cv2
    
    img = cv2.imread('3.jpg')                                                                                                                              
    print (sys.version)                                                                                                                                    
    if sys.version_info[0] < 3:
        raise Exception("Python 3 or a more recent version is required.")
    
    def redo():                                                                                                                                            
        Z = img.reshape((-1,3))                                                                                                                            
        Z = np.float32(Z)                                                                                                 
    
        # define criteria, number of clusters(K) and apply kmeans()                                                                                        
        criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)                                                                           
        K = 2                                                                                                                                              
        start_time = time.time()                                                                                                                           
        ret,label,center=cv2.kmeans(Z,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS)                                                                        
        end_time = time.time()                                                                                                                             
        print("Elapsed cv2 time was %g seconds" % (end_time - start_time))                                                                                 
        print("center")                                                                                                                                    
        print(center)                                                                                                                                      
    
        start_time = time.time()                                                                                                                           
        spcenter, splabel = kmeans2(Z,K,10,1,'points','warn',False)                                                                                        
        end_time = time.time()                                                                                                                             
        print("Elapsed scipy time was %g seconds" % (end_time - start_time))                                                                               
        print("center")                                                                                                                                    
        print(spcenter)                                                                                                                                    
    
        print("diff")                                                                                                                                      
        check = np.abs(spcenter[0][0]-center[0][0])                                                                                                        
        checkflip = np.abs(spcenter[0][0]-center[1][0])                                                                                                    
        if (check < checkflip):                                                                                                                            
            print(np.abs(spcenter-center))                                                                                                                 
        else:                                                                                                                                              
            print("labels are flipped, has no effect on data")                                                                                             
            print(np.abs(spcenter-np.roll(center,1,0)))                                                                                                    
    
        # Now convert back into uint8, and make original image                                                                                             
        #center = np.uint8(center)                                                                                                                         
        res = spcenter[splabel.flatten()]
        res2 = res.reshape((img.shape))                                                                                                                    
        cv2.imwrite('converted.jpg',res2)                                                                                                                  
    
    redo()
    

你可能做不到比这段代码给你的时间更好的了。如果你的解决方案可行,你可以尝试缩小图像。这将导致更快的处理。在

另一个解决方案,如我所提到的,是转移到一个更快的语言,如C。我可以尝试一下,但我不确定你正在使用什么其他代码,它是否可以工作。如果你想走这条路,请告诉我。在

相关问题 更多 >