【背景】
最近有一個需要爲圖片去水印的需求,於是各種折騰開始。
【背景瞭解圖片標準】
圖片使用RGB編碼,RGB色彩模式是工業界的一種顏色標準,是通過對紅(R)、綠(G)、藍(B)三個顏色通道的變化以及它們相互之間的疊加來得到各式各樣的顏色,RGB即是代表紅、綠、藍三個通道的顏色。
【分析圖片】
分析了圖片之後,發現規律:
1、圖片需要的圖形是黑色的
2、水印都是一種顏色:水紅
白色對應#FFFFFF就是 255 255 255
黑色對應#000000 就是 0 0 0
我們用rgb取色工具
發現紅色的字rgb有以下情況:差不多grb的相加和都在200以上,那麼我們寫程序的判斷基準就產生了:就是找到每個像素,如果像素和大於250,並且小於765(不是白色),就將這個像素點重置爲白色:255,255,255。
得到以上邏輯之後,怎樣在代碼中實現?找了幾個python下處理圖像的庫,最終選擇了opencv。於是乎接着就要研究opencv的api了。
具體可以看看opencv的官網:http://opencv.org/
當然一開始你覺得看直接去看手冊很苦逼,也可以看看別人的程序找點感覺了。
【安裝opencv】
其實安裝opencv也是很折騰人的一個事情,mac下安裝opencv安裝可參考:
sudo brew tap homebrew/science sudo brew install OpenCV
注意安裝好了之後,需要將庫的地址做說明,具體看上圖紅框的位置。
有可能還需要
sudo brew update
【具體代碼】
__author__ = 'River' # -*- coding: utf-8 -*- import cv2,os,shutil,datetime,re,time from threading import Thread from hashlib import md5 PICHASH= {} def md5_file(name): try: m = md5() a_file = open(name, 'rb') m.update(a_file.read()) a_file.close() return m.hexdigest() except: return None def nowater(dir,newdir,dirlist): global PICHASH for ppicdir in dirlist: if(os.path.isdir(dir+ppicdir)): sortfiles=os.listdir(dir+ppicdir) if '.DS_Store' in sortfiles: sortfiles.remove('.DS_Store') sortfiles.sort() for oldfile in sortfiles: filetype="."+oldfile.split(".")[len(oldfile.split("."))-1] picname_front=oldfile.split(filetype)[0] oldfile=dir+ppicdir+"/"+oldfile jpgname=picname_front+".jpg" jpgname=newdir+ppicdir+"/"+jpgname try: oldfile_hash=md5_file(oldfile) oldfile_tmphashvalue=PICHASH.get(oldfile_hash) file_object = open('pichash.txt', 'a') file_object.write(oldfile+":"+oldfile_hash+'\n') file_object.close() if(oldfile_tmphashvalue==None):#新文件,已經處理過的圖片,就不會再次處理了 if not os.path.exists(newdir+ppicdir): os.makedirs(newdir+ppicdir) #print oldfile 哈哈 #print jpgname print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")+","+oldfile+",ing\n" img=cv2.imread(oldfile) x,y,z=img.shape if x < 10:#太小文件不處理 print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")+","+jpgname+"文件太小,跳過" elif x >8000:#太大的文件不處理 print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")+","+jpgname+"文件太大,跳過" elif not os.path.exists(jpgname):#這就是最關鍵的代碼了 for i in xrange(x): for j in xrange(y): varP=img[i,j] if sum(varP)>250 and sum(varP)<765 :#大於250,小於765(sum比白色的小) img[i,j]=[255,255,255] #cv2.imwrite(jpgname,img,[int(cv2.IMWRITE_JPEG_QUALITY),70])#linux跑悲劇了 cv2.imwrite(jpgname,img) print "jpgname:"+jpgname PICHASH[oldfile_hash]=oldfile print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")+","+oldfile+",done\n" else: print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")+","+jpgname+"文件已存在,跳過\n" elif(oldfile_tmphashvalue!=None): if(os.path.exists(jpgname)): print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")+","+jpgname+"文件已存在,跳過\n" else: shutil.copyfile(oldfile_tmphashvalue,oldfile) shutil.copyfile(oldfile,jpgname) print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")+","+jpgname+"和老文件一樣,拷貝舊文件,跳過" except Exception,e: print "Exception:",e continue if __name__=='__main__': dir="pic/" newdir="picnew/" list0=[] list1=[] list2=[] list3=[] list4=[] for ppicdir in os.listdir(dir) :#生成多個list,主要是爲了併發處理多個目錄的圖片 if(os.path.isdir(dir+ppicdir)): if (re.compile(r'^[0-1].*').match(str(ppicdir))): list0.append(ppicdir) elif(re.compile(r'^[2-3].*').match(str(ppicdir))): list1.append(ppicdir) elif(re.compile(r'^[4-5].*').match(str(ppicdir))): list2.append(ppicdir) elif(re.compile(r'^[6-7].*').match(str(ppicdir))): list3.append(ppicdir) elif(re.compile(r'^[8-9].*').match(str(ppicdir))): list4.append(ppicdir) else: continue #啓n線程並行處理 Thread(target=nowater,args=(dir,newdir,list0)).start()#這裏只有 Thread(target=nowater,args=(dir,newdir,list1,)).start() Thread(target=nowater,args=(dir,newdir,list2,)).start() Thread(target=nowater,args=(dir,newdir,list3,)).start() Thread(target=nowater,args=(dir,newdir,list4,)).start()
【最終效果】
去除水印之後的效果: