關於“用Python和OpenCV建立一個圖片搜尋引擎的完整指南”在win7作業系統python3.6環境下的測試探索
原部落格文章連結:http://blog.csdn.net/kezunhai/article/details/46417041
---------------
在python3.6中,上面程式需要進行修改:“(axesX, axesY) =(int(w*0.75)/2, int(h*0.75)/2)”需要更改為:“(axesX, axesY) =(int((w*0.75)/2), int((h*0.75)/2))”,否則會 提示錯誤,提示“cv2.ellipse(ellipMask,(cx,cy),(axesX,axesY),0,0,360,255,-1) ”at most 5個引數,結果是8個,因為ellipse只接受整形引數。
另外:
上面的程式還有打字錯誤:
cornerMask = np.zeros(image.shpae[:2],dtype="unit8")
應該為:
cornerMask = np.zeros(image.shape[:2],dtype="unit8")
好像還有一處打字錯誤,我忘記了,喜歡調程式的自己找出來。
好像是shpae應該為shape,自己查詢一下。
-----------------------
注意:
python3.6環境下的opencv3
opencv2和3之間的小坑:hist = cv2.normalize(hist).flatten()改為hist = cv2.normalize(hist,hist).flatten()
-----------
進入python安裝目錄,找到pip目錄,cmd下,進入該目錄,輸入 pip list ,即可看到opencv的版本。
我的版本是:opencv-python<3.3.1>
-------------------------------------------
win7 python3.6執行以下命令
python Search.py -i d:/picture/origin -q d:/picture/q/1.jpg -r d:/picture/test
執行後,出現PermissionError:[Errno 13] Permission denied: 'd:/picture/origin'
程式無法執行,不知道是什麼原理,給了CMD等管理員許可權也不行!
2018年1月14日
-------------------
win7 python3.6環境下(2018年1月16日):
reader = csv.reader()
好像在修改為:
reader = csv.reader(f)
------------------
對於2018-01-14 17:19回覆的帖子進行修正:
win7 python3.6執行以下命令
python Search.py -i d:/picture/origin -q d:/picture/q/1.jpg -r d:/picture/test
執行後,出現PermissionError:[Errno 13] Permission denied: 'd:/picture/origin'
---------------
出現以上錯誤的原因已經找到,屬於引數錯誤導致的!!
具體原因是,因為要寫引數到檔案,結果我指定的路徑是資料夾,而不是具體到檔名稱,現已經更改為“d:/picture/origin/1.csv”,“1.csv”是檔名,這樣就可以運行了。
具體執行過程,應該為:(1)在cmd命令列 視窗輸入以下命令和引數:
python index.py -d d:/picture/origin -i d:/picture/origin/1.csv
-d 指出等待索引的圖片資料夾路徑
-i 指出索引的圖片指紋特徵的存放路徑和檔名稱。
(2)執行第1步後,再執行本步;再在cmd命令列 視窗輸入以下命令和引數:
python Search.py -i d:/picture/origin/1.csv -q d:/picture/q/1.jpg -r d:/picture/test
截止2018年1月16日,還有錯誤,好像圖片指紋寫入到1.csv檔案的內容有誤,錯誤為:
ValueError:could not convert string to float: "0.0norigin\\2.jpg'
後續再來檢視是什麼原因導致的!!!
備註:我d:/picture/origin目錄下的圖片是以 1.jpg 2.jpg ----- 6.jpg來命名的,放了6張不同的圖片來測試程式的。
------------------------------------
2018年1月16日上午9:17分
win7 python3.6環境下,需要把index.py中的
imageID = imagePath[imagePath.rfind("/")+1:]
修改為:
imageID = imagePath[imagePath.rfind("\\")+1:]
------------
find() 是從字串左邊開始查詢子字串匹配到的第一個索引所在位置
rfind()是從字串右邊開始查詢字串匹配到的第一個索引所在位置
例如:
>>> str='this is'
>>> str
'this is'
>>> substr='is'
>>> substr
'is'
>>> str.find(substr)
2
>>> str.rfind(substr)
5
>>>
------------
2018年1月16日上午9:32分
win7 python3.6環境下,需要把index.py中的
output.write("%s,%sn" %(imageID,",".join(features)))
修改為:
output.write("%s,%s\n" %(imageID,",".join(features)))
注意:只是在 n" 前添加了 \
要不然生成的1.csv裡面檔名帶有路徑,而且每幅圖片之後不會回車換行。
-----------------------
2018年1月16日上午:10:30
執行出錯
OpenCV Error:Assertion failed cpp:339:error:<-215>
如果執行出現上面錯誤,是因此給定的目錄不對。
實際應該為:
python Search.py -i d:/picture/origin/1.csv -q d:/picture/q/1.jpg -r d:/picture/origin
說明:“d:/picture/origin”為等待檢索的的圖片放置的資料夾。“d:/picture/q/1.jpg”為等待被查詢的圖片。“-r d:/picture/origin”是顯示查詢結果,從這個資料夾
下按檢索順序提取出相似的圖片。
最終,除錯成功,一定要注意cmd下執行命令的順序,具體為:
(1)
python index.py -d d:/picture/origin -i d:/picture/origin/1.csv
(2)
python Search.py -i d:/picture/origin/1.csv -q d:/picture/q/1.jpg -r d:/picture/origin
備註:目錄下不能有中文的檔名稱,否則會出錯,等待以後解決!!!
python2.x 到 python3.x有很多坑,加上linux作業系統到win7作業系統有一些坑,再有就是目錄、資料夾、檔名,又有很多坑!這些坑要全部填滿才行!!!
---------------------------------------------------------------------------
---------------------------------------------------------------------------
下面是各個檔案的原始碼:
ColorDescriptor.py
"CBIR(Content-Base Image Retrieval)"
import numpy as np
import cv2
class ColorDescriptor:
def __init__(self, bins):
# store the number of bins for the HSV histogram
self.bins = bins
def describe(self, image):
# convert the image into HSV color space
image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
features =[]
# grab the dimensions and compute the center of the image
(h,w) = image.shape[:2]
(cx,cy) = (int(w*0.5), int(h*0.5))
# segment the image
segments =[(0,cx,0,cy),(cx,w,0,cy),(cx,w,cy,h),(0,cx,cy,h)]
# construct an elliptical mask representing the center of the image
(axesX, axesY) =(int((w*0.75)/2), int((h*0.75)/2))
ellipMask = np.zeros(image.shape[:2],np.uint8)#dtype="uint8"
cv2.ellipse(ellipMask,(cx,cy),(axesX,axesY),0.0,0.0,360.0,255.0,-1)
# loop over the segments
for(startX,endX, startY, endY) in segments:
cornerMask = np.zeros(image.shape[:2],np.uint8)#dtype="uint8"
cv2.rectangle(cornerMask,(startX,startY),(endX,endY),255,-1)
cornerMask = cv2.subtract(cornerMask, ellipMask)
# compute the histogram
hist = self.histogram(image, cornerMask)
features.extend(hist)
# compute the ellipse histogram
hist = self.histogram(image, ellipMask)
features.extend(hist)
# return the feature vectr
return features
# define the function of histogram
def histogram(self, image, mask):
# extract the color histogram from the masked region
hist = cv2.calcHist([image],[0,1,2],mask, self.bins,[0,180,0,256,0,256])
hist = cv2.normalize(hist,hist).flatten()
return hist
-------------------------------------------------------------
index.py
"CBIR(Content-Base Image Retrieval)--Extract Features and Indexing"
import ColorDescriptor
import argparse
import glob
import cv2
ap = argparse.ArgumentParser()
ap.add_argument("-d", "--dataset", required=True, help="Path to the directory that cntains the images to be indexed")
ap.add_argument("-i", "--index", required=True, help="Path to where the computed index will be stored")
args = vars(ap.parse_args())
cd = ColorDescriptor.ColorDescriptor((8,12,3))
#Open the output index file for writing
output = open(args["index"],"w")
# use glob to grab the image paths and loop over them
for imagePath in glob.glob(args["dataset"]+"/*.jpg"):
# extract the image ID from the image
imageID = imagePath[imagePath.rfind("\\")+1:]
image = cv2.imread(imagePath)
# describe the image
features = cd.describe(image)
# write feature to file
features = [str(f) for f in features]
output.write("%s,%s\n" %(imageID,",".join(features)))
# close index file
output.close()
-------------------------------------
Searcher.py
"CBIR(Content-Base Image Retrieval)--Similarity and Search"
import numpy as np
# use for processing index.csv
import csv
class Searcher:
def __init__(self, indexPath):
self.indexPath = indexPath
def chi2_distance(self, histA, histB, eps=1e-10):
# compute the chi-squred distance
d = 0.5*np.sum([((a-b)**2)/(a+b+eps) for(a,b) in zip(histA,histB)])
return d
def search(self, queryFeatures, limit=10):
results = {}
# open the index file for reading
with open(self.indexPath) as f:
# initialize the CSV reader
reader = csv.reader(f)
# loop over the rows in the index
for row in reader:
# parse out the imageID and features,
# then compute the chi-squared distance
features = [float(x) for x in row[1:]]
d = self.chi2_distance(features, queryFeatures)
results[row[0]] = d
f.close()
results = sorted([(v,k) for (k,v) in results.items()])
return results[:limit]
#def chi2_distance(self, histA, histB, eps=1e-10):
## compute the chi-squred distance
#d = 0.5*np.sum([((a-b)**2)/(a+b+eps) for(a,b) in zip(histA,histB)])
#return d
--------------------------------------Search.py
"CBIR(Content-Base Image Retrieval)--Search"
import argparse
import cv2
import ColorDescriptor
import Searcher
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--index", required=True, help="Path to where the computed index will be stored")
ap.add_argument("-q", "--query", required=True, help="Path to query image")
ap.add_argument("-r", "--result_path", required = True, help="Path to the result Path")
args = vars(ap.parse_args())
cd = ColorDescriptor.ColorDescriptor((8,12,3))
# load the query image and describe it
query = cv2.imread(args["query"])
features = cd.describe(query)
# perform the search
searcher = Searcher.Searcher(args["index"])
results = searcher.search(features)
# display the query
cv2.imshow("Query", query)
# loop over the results
for(score, resultID) in results:
# load the result image and display it
print(args["index"]+"/"+resultID)
result = cv2.imread(args["result_path"]+"/"+resultID)
cv2.imshow("Result",result)
cv2.waitKey(0)