<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          用 OpenCV 去除圖片中的水印,騷操作!

          共 9069字,需瀏覽 19分鐘

           ·

          2021-07-05 07:40

          點(diǎn)擊上方小白學(xué)視覺”,選擇加"星標(biāo)"或“置頂

          重磅干貨,第一時間送達(dá)

          本文轉(zhuǎn)自|AI算法與圖像處理

          這兩天在 Stackoverflow 上面看到了一個有趣的案例,是關(guān)于OpenCV 的一個討論,討論的主題就是如何用 OpenCV 來去除下面圖片中的水印,原圖如下;

          題主想把紙張中的 黑色圓環(huán)去掉只留下背景,因此一些感興趣的 CV 愛好者在下面寫上自己的想法、并貼上自己的解決代碼,看到關(guān)于這個主題的答案后,只能感嘆真正的大佬,都是從實(shí)踐場景出發(fā)來解決問題,因為篇幅有限,在文章中只貼上得票最高的兩個問答思路及代碼, 讓我們感受下他們思路的巧妙之處!

          作者:Joel G

          這老哥的思路,總體為五部分

          • 1,首先將圖像轉(zhuǎn)化為灰度圖記為 A;

          • 2,利用霍夫圓在 A 中檢測最大的橢圓,然后在新的圖像中創(chuàng)建相同半徑的圓得到 B;

          • 3,對灰度圖和繪制圓的圖像,應(yīng)用OpenCV 的 bitwise_and 與運(yùn)算,在原灰度圖像 A 中提取只包含橢圓圖像區(qū)域記為 C;

          • 4,對圖像 C 設(shè)置合適的閾值進(jìn)行文字提取最終得到 D;

          • 5, 對 圖像 A 和 D 做bitwise_or 操作,即能夠得到最終圖像 E;

          以下是在自己機(jī)子上跑出來的結(jié)果,從左到右依次對應(yīng)上面的 A,C,D,E;效果如下

          這個方法整體大概思想,先提取圖像中圓環(huán)部分區(qū)域,對圓環(huán)內(nèi)的文字做閾值分割進(jìn)行提取,最后將提取到的圖像區(qū)域在初始圖像中進(jìn)行替換,這里答主主要用到了三種重要算法:圖像位運(yùn)算(和、或)閾值分割霍夫圓檢測,下面就是這個思路的代碼部分,原答主用的是 C++ ,因為我做的是 Python 教程,就用 Python 轉(zhuǎn)換了一下

          import cv2
          import numpy as np

          if __name__ =='__main__':
              img_path = "F:/Data/Ceshi1/shuiyin.jpg"

              img1 = cv2.imread(img_path)
              cv2.namedWindow('img1',cv2.WINDOW_FREERATIO)
              cv2.imshow('img1',img1)

              # 轉(zhuǎn)化為 灰度圖
              gray = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
              # 創(chuàng)建一個白畫布
              ellipse_img = np.full((img1.shape[0],img1.shape[1],3),0,dtype = np.uint8)
              print(ellipse_img.shape,ellipse_img[0][0])
              gray = cv2.GaussianBlur(gray,(5,5),0) # 高斯處理
              # 應(yīng)用霍夫圓檢測,檢測出所有圓
              circles = cv2.HoughCircles(gray,cv2.HOUGH_GRADIENT,1,gray.shape[0]/8,100,100,100,0)


              # 找到最大的圓
              measure = 0.0
              x = 0.0
              y = 0.0
              for circle in (circles[0]):
                  if circle[2] > measure:
                      measure = circle[2]
                      x = circle[0]
                      y = circle[1]

              # 繪制圓
              cv2.circle(img1,(x,y),3,(0,255,0),-1,8,0)
              cv2.circle(img1,(x,y),int(measure),(0,255,0),2,8,0)
              # 繪制相同大小的圓
              ellipse_img =  cv2.ellipse(ellipse_img,(x,y),(int(measure),int(measure)),0,0,360,(255,255,255),-1,8)
              print(f'center x is {x} ,y is {y}, radius is {measure}')
              ellipse_img = cv2.cvtColor(ellipse_img,cv2.COLOR_BGR2GRAY)

              result = cv2.bitwise_and(gray,ellipse_img)


              cv2.namedWindow('bitwise and',cv2.WINDOW_FREERATIO)
              cv2.imshow('bitwise and',result)

              # 估計圓圖像像素強(qiáng)度
              x = result[int(x+30)][int(y)]
              print(f'intensity is  {x}')


              # 閾值分割
              _,ellipse_img = cv2.threshold(result,int(x) - 10,250,cv2.THRESH_BINARY)
              # print('ellipse_img shape is {}'.format(ellipse_img.shape))
              cv2.namedWindow('threshold',cv2.WINDOW_FREERATIO)
              cv2.imshow('threshold',ellipse_img)

              # 使用 bitwise_or 方法
              print('shape ------------\n')
              print(ellipse_img.shape,gray.shape)
              res = cv2.bitwise_or(gray,ellipse_img)

              cv2.namedWindow('bitwise_or',cv2.WINDOW_FREERATIO)
              cv2.imshow('bitwise_or',res)

              cv2.waitKey(0)

          最終結(jié)果預(yù)覽比對

          上面是第一種實(shí)現(xiàn)方法,這種方法思路主要用到閾值分割,從最終結(jié)果來看確實(shí)去掉了水印,但還是有一定的瑕疵:

          • 比如圓內(nèi)文字背景與圓外背景是不一樣的,存在很大色差,并且圓內(nèi)的文字提取結(jié)果來看是不完整的;
          • 此方法不具有普遍性,因為這類方法只能針對于圓形水印,假設(shè)水印是不規(guī)則多邊形此方法可能就會失效

          下面介紹第二種思路,與第一種有相似的地方,也用到了閾值分割、圖像像素位運(yùn)算 相關(guān)算法,但同卻又有自己的獨(dú)特地方,從客觀角度分析來看,這種方法的最終結(jié)果會更好一點(diǎn)

          作者: dhanushka

          思路主要分為四部分

          • 1,源圖像記為 A,用形態(tài)學(xué)濾波器刪除圖像中文字區(qū)域,得到的圖像記為 B;
          • 2,獲取A,B 圖像的之差,用 A-B ,得到區(qū)別后再用閾值分割進(jìn)行處理,得到 C;
          • 3,閾值分割背景圖像,提取水印覆蓋的黑色部分記為 D;
          • 4,從 A 中提取在區(qū)域 D 中的像素,再用閾值分割方法分割像素,最終將提取到的像素貼到 B 中,得到最終去除水印的圖像

          代碼貼在下方

          import cv2
          import numpy as np

          if __name__ =='__main__':
              img_path = "F:/Data/Ceshi1/shuiyin.jpg"
              im = cv2.imread(img_path)

              gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

              background = gray.copy()
              for i in range(1,5):
                  kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(2*i+1,2*i+1))
                  # print('kernel size is ',kernel)
                  background = cv2.morphologyEx(background,cv2.MORPH_CLOSE,kernel)
                  background = cv2.morphologyEx(background,cv2.MORPH_CLOSE,kernel)

              diff = background - gray # 計算差距

              cv2.namedWindow('diff',cv2.WINDOW_FREERATIO) # 獲取圖像中前景背景之差
              cv2.imshow('diff',background)
              # 閾值分割獲取黑色字體
              _,bw = cv2.threshold(diff,0,255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
              # 閾值分割獲取黑色區(qū)域
              cv2.namedWindow('bw_before', cv2.WINDOW_FREERATIO)
              cv2.imshow('bw_before', bw)


              _,dark = cv2.threshold(background,0,255,cv2.THRESH_BINARY_INV|cv2.THRESH_OTSU)

              darkpix = cv2.countNonZero(dark)# 獲取 dark非0d圖像像素個數(shù)
              darkpix = [0]*darkpix
              index = 0
              cv2.namedWindow('gray', cv2.WINDOW_FREERATIO)
              cv2.imshow('gray', gray)



              for r in range(dark.shape[0]):
                  for c in range(dark.shape[1]):
                      if(dark[r][c]):
                          darkpix[index]  = gray[r][c]
                          index = index +1

              # 閾值分割 dark 區(qū)域 因此我們在里面得到更深的像素
              darkpix = np.array(darkpix)
              _,darkpix = cv2.threshold(darkpix,0,255,cv2.THRESH_BINARY | cv2.THRESH_OTSU)

              cv2.namedWindow('darkpix', cv2.WINDOW_FREERATIO)
              cv2.imshow('darkpix', darkpix)

              # 把 取到的像素粘貼到 其渠道的 darker pixels

              cv2.namedWindow('dark',cv2.WINDOW_FREERATIO)
              cv2.imshow('dark',dark)

              index = 0
              for r in range(dark.shape[0]):
                  for c in range(dark.shape[1]):
                      if (dark[r][c]):
                          bw[r][c] =  darkpix[index]
                          index = index +1

              cv2.namedWindow('bw',cv2.WINDOW_FREERATIO)
              cv2.imshow('bw',bw)
              cv2.waitKey(0)

          效果預(yù)覽對比

          相對第一種方法,第二種方法實(shí)用性更強(qiáng)一點(diǎn),無論圖像前景水印為什么形狀的,這種方法都可適用(水印區(qū)域與其他背景像素強(qiáng)度差別大,且水印區(qū)域是連接在一起的)。


          如果考慮到商用途徑,只用 OpenCV 來解決復(fù)雜場景的圖片水印問題,是不現(xiàn)實(shí)的,還需人工的干涉;但不現(xiàn)實(shí)并不代表它沒有用,對于前后像素值較大、簡單場景的水印,OpenCV 是完全可行的,若是再加上一個批量操作,變得更可了,大大解放我們的雙手!


          并且這兩種思路中用到的的一些方法,是值得我們借鑒的,比如 圖像像素或與和操作、形態(tài)學(xué)過濾、霍夫圓檢測等技術(shù),可借助于這些方法應(yīng)用到其它場景,例如提取圖像中圓形區(qū)域、行人路上斑馬線檢測、去除不規(guī)則圖像連接區(qū)域等。


          下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程
          在「小白學(xué)視覺」公眾號后臺回復(fù):擴(kuò)展模塊中文教程即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺、目標(biāo)跟蹤、生物視覺、超分辨率處理等二十多章內(nèi)容。

          下載2:Python視覺實(shí)戰(zhàn)項目52講
          小白學(xué)視覺公眾號后臺回復(fù):Python視覺實(shí)戰(zhàn)項目即可下載包括圖像分割、口罩檢測、車道線檢測、車輛計數(shù)、添加眼線、車牌識別、字符識別、情緒檢測、文本內(nèi)容提取、面部識別等31個視覺實(shí)戰(zhàn)項目,助力快速學(xué)校計算機(jī)視覺。

          下載3:OpenCV實(shí)戰(zhàn)項目20講
          小白學(xué)視覺公眾號后臺回復(fù):OpenCV實(shí)戰(zhàn)項目20講即可下載含有20個基于OpenCV實(shí)現(xiàn)20個實(shí)戰(zhàn)項目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。

          交流群


          歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學(xué)影像、GAN算法競賽等微信群(以后會逐漸細(xì)分),請掃描下面微信號加群,備注:”昵稱+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進(jìn)入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~


          瀏覽 59
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91人人澡人人爽人人少妇 | 青草福利在线视频 | 国产一级片色 | 国产一级a毛一级a毛免费视频 | 91人妻一区二区三 |