OpenCV中imshow函數(shù)遇到的坑

最近在學(xué)習(xí)OpenCV,在自己實(shí)現(xiàn)rober,LOG等算子卷積的時候,遇到了一些坑,先上代碼

import cv2
import numpy as np
import os
import copy
# 邊緣檢測
filename = os.path.abspath('第二次作業(yè)/lena.jpg') 
lena = cv2.imread(filename)

# 實(shí)現(xiàn)robert,Sobel和LOG邊緣提取
gray = cv2.imread(os.path.abspath('第二次作業(yè)/bear.jpg'),0)
gray = cv2.cvtColor(lena,cv2.COLOR_BGR2GRAY)
w,h = gray.shape
robert_img = gray.copy()
sobel_img = gray.copy()
log_img = gray.copy()
robertx,roberty = np.array([-1,-1,1,1]),np.array([0,1,-1,0])
sobel = np.array([1,0,-1,2,0,-2,1,0,-1])
LOG = np.array([-2,-4,-4,-4,-2,-4,0,8,0,-4,-4,8,24,8,-4,-4,0,8,0,-4,-2,-4,-4,-4,-2])
for i in range(w-2):
    for j in range(h-2):
        origin1 = np.array(gray[i:i+2,j:j+2]).flatten()
        origin2 = np.array(gray[i:i+3,j:j+3]).flatten()
        origin3 = np.array(gray[i:i+5,j:j+5]).flatten()
        value = abs(origin1.dot(robertx))
        robert_img[i][j] = value
        if value != robert_img[i,j]:
            print(value,'-----',robert_img[i,j])
        sobel_img[i][j] = origin2.dot(sobel)
        if(i<w-4 and j<h-4):
            value = origin3.dot(LOG)
            log_img[i][j] = value

cv2.imshow('origin',gray)
cv2.imshow('robert',robert_img)
cv2.imshow('sobel',sobel_img)
cv2.imshow('LOG',log_img)
cv2.imshow('sobelopen',cv2.Sobel(gray,cv2.CV_64F,1,0,ksize=3))

cv2.waitKey()
cv2.destroyAllWindows()

在建立新的圖片用于存儲計算好的結(jié)果時,我使用了如下方法

robert_img = gray.copy()
sobel_img = gray.copy()
log_img = gray.copy()

結(jié)果顯示如下:


image.png

可以看到LOG算子的計算結(jié)果明顯不對,使用如下方式創(chuàng)建圖像:

robert_img = np.empty(gray.shape)
sobel_img = np.empty(gray.shape)
log_img = np.empty(gray.shape)

結(jié)果如下:


image.png

再換成如下方式:

robert_img = np.empty_like(gray)
sobel_img = np.empty_like(gray)
log_img = np.empty_like(gray)
image.png

結(jié)果和第一個一樣的
只是改變了創(chuàng)建圖片的方式,怎么結(jié)果就這么不一樣呢?
經(jīng)過仔細(xì)的調(diào)試,發(fā)現(xiàn),由于不同算子經(jīng)過卷積計算后,結(jié)果的值不一定在[0,255]之間,所以在將結(jié)果賦值給創(chuàng)建的數(shù)據(jù)時,會將結(jié)果自動轉(zhuǎn)成數(shù)據(jù)的類型,而轉(zhuǎn)換的結(jié)果并不是我們想要的,所以出現(xiàn)了錯誤。
這里就提一下np.empty()和np.empty_like()的區(qū)別,前者如果沒有指定數(shù)據(jù)類型(參數(shù)dtype進(jìn)行設(shè)置),那么會默認(rèn)為浮點(diǎn)類型,而后者需要傳入一個存在的數(shù)據(jù),所以新建的數(shù)據(jù)會設(shè)定成這個數(shù)據(jù)的類型。
那么初始化為浮點(diǎn)的類型,最后結(jié)果為什么顯示是錯誤的呢?這里就是imshow函數(shù)的一個坑,我們先看看這個函數(shù)在python中的注釋:


image.png

大概翻譯一下,就是說如果數(shù)據(jù)類型是uint8,那么將直接顯示,如果是16位或者32位整型,那么將該值除以256,得到[0,255]的范圍進(jìn)行顯示,如果是一個浮點(diǎn)數(shù),那么將其乘以255,那么[0,1]就轉(zhuǎn)換成[0,255]的值進(jìn)行顯示。
所以,就出現(xiàn)了之前代碼出現(xiàn)的問題。但是這里的描述仍然不夠詳盡,比如16位整型值是負(fù)的怎么處理,浮點(diǎn)數(shù)大于1的怎么處理,查了很多地方都沒有看看,如果有誰知道,麻煩告訴我一下。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容