1. 程式人生 > >[python3 OpenCV3填坑之旅]解決影象數學運算後無法正確顯示的問題

[python3 OpenCV3填坑之旅]解決影象數學運算後無法正確顯示的問題

最近用的OpenCV python3 開發場景識別的應用,遇到了在影象進行數學邏輯運算後無法真確顯示的問題,問題程式碼如下:

out = 1*((img[:,:,2]>img[:,:,1])&(img[:,:,1]>img[:,:,0]))
print(out.shape,np.sum(out))
while (True):
    cv2.imshow("myWin", (out*255))
    if(cv2.waitKey(1000//12) &  0xff == ord("q")):
        #cv2.imwrite("test/chess_deal.png", out*255)
        break
cv2.destroyAllWindows()

顯示輸出out輸出圖片的形狀與資料都沒有問題,可就是無法正確顯示。
最後通過一個語句發現到了問題所在:

print(out.dtype)

輸出結果為:

int64

發現原因所在,由於OpenCV處理資料需要uint8型別,影象進行數學邏輯運算時,被轉換成了int64,如果想OpenCV正確顯示,需要進行資料型別轉換:

out_deal = out.astype(np.uint8)

完整程式碼如下(OpenCV做的火焰動態檢測裝置):

import cv2
import numpy as np
"""人眼的視網膜上有兩類感光器:錐狀體和桿狀體。錐狀體主要位於視網膜的中間部分,稱之為中央凹,且對顏色高度敏感,稱為白晝視覺或亮視覺;
桿狀體分佈面積較大,用來給出視野內的一般的總體影象,沒有彩色感覺,而對低照明度敏感,稱為微光視覺或暗視覺。由於錐狀體對紅、綠、藍三種
顏色的光很敏感,因此一般用於人眼觀看的顏色模型是RGB模型。一般來說,無論是在網上下載的圖片或視訊,還是從攝像機得來的錄影,都是RGB
模型。所以,我們從網上下載了一幅火焰影象,不用進行任何的顏色模型轉換就可以使用RGB顏色判據來提取區域。

    對於普通的火焰來說,它的紅色分量和綠色分量會很大,並且綠色分量會大於藍色分量,所以我們設下的簡單判據是:
                    R > R_avg    AND
                    G > G_avg    AND
                    R > G > B
    其中,R_avg為紅色分量的均值。
    在OpenCV1.0中實現很簡單,下面先擺出程式碼
--------------------- 
作者:電磁炮X 
來源:CSDN 
原文:https://blog.csdn.net/qq_27569955/article/details/51502824 
版權宣告:本文為博主原創文章,轉載請附上博文連結!
"""
print(cv2.__version__)


img = cv2.imread("test/flame1.jpg")

line, cols, chl = img.shape
img_avg = []
for i in range(chl):
    img_avg.append(np.average(img[:,:,i]))
overAvg = []
for i in range(chl):
    overAvg.append(img[:,:,i]>img_avg[i])

#out = (overAvg[1] and overAvg[0]) and ((img[:,:,2]>img[:,:,1]) and (img[:,:,1]>img[:,:,0]))
out = 1*((overAvg[2]&overAvg[1])&((img[:,:,2]>img[:,:,1])&(img[:,:,1]>img[:,:,0])))

out = out
print(np.sum(out)/(line * cols)*100,out.shape)
print(out.dtype)
print((out*255).astype(np.uint8).dtype)
while (True):
    cv2.imshow("myWin", (out*255).astype(np.uint8))
    if(cv2.waitKey(1000//12) &  0xff == ord("q")):
        #cv2.imwrite("test/chess_deal.png", (out*255).astype(np.uint8))
        break

cv2.destroyAllWindows()