OpenCV_008-OpenCV 中的圖像算術(shù)運算

本文主要內(nèi)容來自于 OpenCV-Python 教程核心操作 部分,這個部分的主要內(nèi)容如下:

目標

  • 學習一些圖像的算術(shù)運算操作,比如加、減、位運算,等等。
  • 學習這些函數(shù):cv.add(),cv.addWeighted(),等等。

圖像加法

我們可以利用 OpenCV 的函數(shù),cv.add(),或簡單地通過 numpy 操作 res = img1 + img2,將兩幅圖像加起來。兩幅圖像應該具有相同的深度和類型,或者第二幅圖像可以僅僅是個標量值。

注意
OpenCV 的加法和 Numpy 的加法是有區(qū)別的。OpenCV 加法是飽和運算,而 Numpy 加法是模運算。

比如,考慮下面的例子:

def diff_add():
    x = np.uint8([250])
    y = np.uint8([10])

    print(cv.add(x,y)) # 250+10 = 260 => 255
    print(x + y)  # 250+10 = 260 % 256 = 4

這幾行代碼的輸出如下:

[[255]]
[4]

當將兩個圖像相加時,這將更加明顯。堅持使用 OpenCV 函數(shù),因為它們會提供更好的結(jié)果。

圖像混合

這也是一個圖像相加操作,但會給不同的圖像以不同的權(quán)重,為了給人一種混合或透明的感覺。圖像相加操作按以下公式進行:

g(x) = (1 - alpha)f_0(x) + alphaf_1(x)

通過從 0 -> 1 改變 alpha 的值,我們可以執(zhí)行一個從一幅圖像到另一幅圖像之間很酷的轉(zhuǎn)換。

這里我們拿兩幅圖像來混合。給第一個圖像一個權(quán)重 0.7,給第二個圖像一個權(quán)重 0.7。 cv.addWeighted() 對圖像應用如下的公式:

dst = alpha * img1 + beta * img2 + gamma

這里的 gamma 我們?nèi)?0。

def image_blending():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    file_ml = cv.samples.findFile('ml.png')
    img1 = cv.imread(file_ml)

    file_logo = cv.samples.findFile('opencv-logo.png')
    img2 = cv.imread(file_logo)
    print(img1.shape)
    img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))
    print(img2.shape)
    dst = cv.addWeighted(img1, 0.7, img2, 0.3, 0)

    plt.subplot(131), plt.imshow(img1, 'gray'), plt.title('ORIGINAL')
    plt.subplot(132), plt.imshow(img2, 'gray'), plt.title('REPLICATE')
    plt.subplot(133), plt.imshow(dst, 'gray'), plt.title('REFLECT')

    plt.subplots_adjust(wspace=0.4, hspace=0.4)

    plt.show()

由于上面的兩幅圖像大小不一樣,因而通過 cv.resize() 將其中一幅圖像的大小做調(diào)整,以便后面的混合操作可以正常執(zhí)行。檢查最終的結(jié)果如下:

Image

下面這個例子演示如上相同的函數(shù),但引入 cv.hconcat() 來將原始圖像和結(jié)果圖像水平拼接起來,以另一種方式展示結(jié)果:

def image_blending1():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    file_ml = cv.samples.findFile('ml.png')
    img1 = cv.imread(file_ml)

    file_logo = cv.samples.findFile('opencv-logo.png')
    img2 = cv.imread(file_logo)
    print(img1.shape)
    img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))
    print(img2.shape)
    dst = cv.addWeighted(img1, 0.7, img2, 0.3, 0)

    images = [img1, img2, dst]
    img4 = cv.hconcat(images)

    cv.imshow('Image', img4)
    cv.waitKey(0)
    cv.destroyAllWindows()

檢查最終的結(jié)果如下:

Image

下面這個示例則通過圖像混合,實現(xiàn)一個漸入和漸出的動畫效果:

def image_blending2():
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    file_ml = cv.samples.findFile('ml.png')
    img1 = cv.imread(file_ml)

    file_logo = cv.samples.findFile('opencv-logo.png')
    img2 = cv.imread(file_logo)
    img2 = cv.resize(img2, (img1.shape[1], img1.shape[0]))

    weight = 0.01
    step = 0.02
    while True:
        dst = cv.addWeighted(img1, weight, img2, 1 - weight, 0)
        cv.imshow('Image', dst)

        key = cv.waitKey(35)
        if key == ord('q'):
            break

        weight += step
        if (weight > 1.0):
            step = -step
        elif weight < 0:
            step = -step

    cv.destroyAllWindows()

位操作

這里包括位 AND,OR,NOT 和 XOR 操作。在提取圖像的任何部分(我們將在接下來的章節(jié)中看到)、定義和使用非矩形 ROI 等時,它們將非常有用。下面我們將看到一個如何更改圖像特定區(qū)域的示例。

我想把 OpenCV logo 放到一幅圖像上面。如果我將兩幅圖像相加,則它將改變顏色。如果我混合它們,我得到一個透明效果。但我希望它是不透明的。如果它是一個矩形區(qū)域,我可以使用 ROI,就像我們在前面的章節(jié)中做的那樣。但 OpenCV logo 不是一個矩形。因而,我們可以用位操作來實現(xiàn),如下所示:

def bitwise_operations():
    # Load two images
    cv.samples.addSamplesDataSearchPath("/media/data/my_multimedia/opencv-4.x/samples/data")
    img1 = cv.imread(cv.samples.findFile('messi5.jpg'))
    img2 = cv.imread(cv.samples.findFile('opencv-logo-white.png'))

    # I want to put logo on top-left corner, So I create a ROI
    rows, cols, channels = img2.shape
    roi = img1[0:rows, 0:cols]

    # Now create a mask of logo and create its inverse mask also
    img2gray = cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
    ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
    mask_inv = cv.bitwise_not(mask)

    images = [img2gray, mask, mask_inv]
    image = cv.hconcat(images)

    # Now black-out the area of logo in ROI
    img1_bg = cv.bitwise_and(roi, roi, mask=mask_inv)

    # Take only region of logo from logo image.
    img2_fg = cv.bitwise_and(img2, img2, mask=mask)

    # Put logo in ROI and modify the main image
    dst = cv.add(img1_bg, img2_fg)

    images2 = [img1_bg, img2_fg, dst]
    image2 = cv.hconcat(images2)

    img1[0:rows, 0:cols] = dst

    plt.subplot(211), plt.imshow(image, 'gray'), plt.title('MASK')
    plt.subplot(212), plt.imshow(image2, 'gray'), plt.title('ROI')

    plt.subplots_adjust(wspace=0.1, hspace=0.3)

    plt.show()

執(zhí)行上面的代碼,MASK 和 ROI 區(qū)域的變化如下圖:

MASK 和 ROI

查看最終的結(jié)果。左圖顯示了我們創(chuàng)建的蒙版。右圖展示了最終的結(jié)果。為了獲得更好的理解,顯示上面代碼中所有的中間圖像,特別是 img1_bgimg2_fg。

Image

將左邊圖像和右邊圖像拼接起來并顯示的代碼如下:

    image4 = np.zeros((img1.shape[0], img2.shape[1], 3), np.uint8)
    merged = cv.merge((mask, mask, mask))
    image4[0:rows, 0:cols] = merged

    img1[0:rows, 0:cols] = dst

    images5 = [image4, img1]
    dest = cv.hconcat(images5)

    cv.imshow('res', dest)
    cv.waitKey(0)
    cv.destroyAllWindows()

其它資源

練習

  1. 使用 cv.addWeighted 函數(shù),創(chuàng)建文件夾中圖像的幻燈片放映,并在圖像之間平滑過渡。

參考文檔

Arithmetic Operations on Images

OPENCV基礎(chǔ)(三):圖像的混合

opencv實現(xiàn)幾幅圖像拼接成一整幅大圖

Done.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,835評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,676評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,730評論 0 380
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,118評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,873評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,266評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,330評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,482評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,036評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,846評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,025評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,575評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,279評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,684評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,953評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,751評論 3 394
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,016評論 2 375

推薦閱讀更多精彩內(nèi)容