平台:win10 x64 +JetBrains PyCharm 2018.2.4 x64 +Anaconda3(python3.7.0+opencv3.4.5)
Issue说明:同学发了个python代码,想实现下brisk,帮同学解决,自己试验了下,但是报错ImportError:检查opencv的安装
from os import path
import sys
import numpy as np
try:
import cv2
except ImportError:
print('Couldn\'t find opencv so trying to use the fallback' \
' cv2.pyd (only for windows).')
from _cv2_fallback import cv2
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Helper Functions
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
def polygon_area(vertices):
"""Calculate the area of the vertices described by the sequence of vertices.
Thanks to Darel Rex Finley: http://alienryderflex.com/polygon_area/
"""
area = 0.0
X = [float(vertex[0]) for vertex in vertices]
Y = [float(vertex[1]) for vertex in vertices]
j = len(vertices) - 1
for i in range(len(vertices)):
area += (X[j] + X[i]) * (Y[j] - Y[i])
j = i
return abs(area) / 2 # abs in case it's negative
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Fundamental Parts
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# alternative detectors, descriptors, matchers, parameters ==> different results
detector = cv2.BRISK(thresh=10, octaves=1)
extractor = cv2.DescriptorExtractor_create('BRISK') # non-patented. Thank you!
matcher = cv2.BFMatcher(cv2.NORM_L2SQR)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Object Features
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
obj_original = cv2.imread(path.join('source_images', 'object.png'),
cv2.CV_LOAD_IMAGE_COLOR)
if obj_original is None:
print ('Couldn\'t find the object image with the provided path.')
sys.exit()
# basic feature detection works in grayscale
obj = cv2.cvtColor(obj_original, cv2.COLOR_BGR2GRAY)
# mask with white in areas to consider, black in areas to ignore
obj_mask = cv2.imread(path.join('source_images', 'object_mask.png'),
cv2.CV_LOAD_IMAGE_GRAYSCALE)
if obj_mask is None:
print ('Couldn\'t find the object mask image with the provided path.' \
' Continuing without it.')
# keypoints are "interesting" points in an image:
obj_keypoints = detector.detect(obj, obj_mask)
# this lines up each keypoint with a mathematical description
obj_keypoints, obj_descriptors = extractor.compute(obj, obj_keypoints)
print ('Object Summary *************************************************')
print (' {} keypoints'.format(len(obj_keypoints)))
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Scene Features
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
scene_original = cv2.imread(path.join('source_images', 'scene.png'),
cv2.CV_LOAD_IMAGE_COLOR)
if scene_original is None:
print ('Couldn\'t find the scene image with the provided path.')
sys.exit()
scene = cv2.cvtColor(scene_original, cv2.COLOR_BGR2GRAY)
scene_mask = cv2.imread(path.join('source_images', 'scene_mask.png'),
cv2.CV_LOAD_IMAGE_GRAYSCALE)
if scene_mask is None:
print ('Couldn\'t find the scene mask image with the provided path.' \
' Continuing without it.')
scene_keypoints = detector.detect(scene, scene_mask)
scene_keypoints, scene_descriptors = extractor.compute(scene, scene_keypoints)
print ('Scene Summary **************************************************')
print (' {} keypoints'.format(len(scene_keypoints)))
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Match features between the object and scene
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
min_matches = 3
matches = matcher.match(obj_descriptors, scene_descriptors)
if len(matches) < min_matches:
print ('Not enough matches found between the image and scene keypoints.')
sys.exit()
#do some filtering of the matches to find the best ones
distances = [match.distance for match in matches]
min_dist = min(distances)
avg_dist = sum(distances) / len(distances)
# basically allow everything except awful outliers
# a lower number like 2 will exclude a lot of matches if that's what you need
min_multiplier_tolerance = 10
min_dist = min_dist or avg_dist * 1.0 / min_multiplier_tolerance
good_matches = [match for match in matches if
match.distance <= min_multiplier_tolerance * min_dist]
print ('Match Summary **************************************************')
print (' {} / {} good / total matches'.format(len(good_matches),
len(matches)))
if len(good_matches) < min_matches:
print ('not enough good matches to continue')
sys.exit()
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Calculate the shape of the object discovered in the scene.
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# extract the positions of the good matches within the object and scene
obj_matched_points = np.array([obj_keypoints[match.queryIdx].pt
for match in good_matches])
scene_matched_points = np.array([scene_keypoints[match.trainIdx].pt
for match in good_matches])
# find the homography which describes how the object is oriented in the scene
# also gets a mask which identifies each match as an inlier or outlier
homography, homography_mask = cv2.findHomography(obj_matched_points,
scene_matched_points,
cv2.RANSAC, 2.0)
print ('Homography Summary **************************************************')
print (' {} / {} inliers / good matches'.format(np.sum(homography_mask),
len(homography_mask)))
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Extract sizes and coordinates
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
obj_h, obj_w = obj.shape[0:2]
scene_h, scene_w = scene.shape[0:2]
#corners: opencv uses (top left, top right, bottom right, bottom left)
obj_top_left = (0, 0)
obj_top_right = (obj_w, 0)
obj_bottom_right = (obj_w, obj_h)
obj_bottom_left = (0, obj_h)
object_corners_float = np.array([obj_top_left, obj_top_right,
obj_bottom_right, obj_bottom_left],
dtype=np.float32)
#corners of the object in the scene (I don't know about the reshaping)
obj_in_scene_corners_float =\
cv2.perspectiveTransform(object_corners_float.reshape(1, -1, 2),
homography).reshape(-1, 2)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Visualize the matching results
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# create a combined image of the original object and the scene
blue = (255, 0, 0)
green = (0, 255, 0)
red = (0, 0, 255)
combo_image = np.zeros((max(scene_h, obj_h), scene_w + obj_w), np.uint8)
combo_image[0:obj_h, 0:obj_w] = obj # copy the obj into the combo image
combo_image[0:scene_h, obj_w:obj_w + scene_w] = scene # same for the scene
combo_image = cv2.cvtColor(combo_image, cv2.COLOR_GRAY2BGR) # color for output
# draw a polygon around the object in the scene
obj_in_scene_offset_corners_float = obj_in_scene_corners_float + (obj_w, 0)
cv2.polylines(combo_image, [np.int32(obj_in_scene_offset_corners_float)],
True, blue, 2)
# mark inlier and outlier matches
for (x1, y1), (x2, y2), inlier in zip(np.int32(obj_matched_points),
np.int32(scene_matched_points),
homography_mask):
if inlier:
#draw a line with circle ends for each inlier
cv2.line(combo_image, (x1, y1), (x2 + obj_w, y2), green)
cv2.circle(combo_image, (x1, y1), 4, green, 2)
cv2.circle(combo_image, (x2 + obj_w, y2), 4, green, 2)
else:
#draw a red x for outliers
r = 2
weight = 2
cv2.line(combo_image,
(x1 - r, y1 - r), (x1 + r, y1 + r), red, weight)
cv2.line(combo_image,
(x1 - r, y1 + r), (x1 + r, y1 - r), red, weight)
cv2.line(combo_image,
(x2 + obj_w - r, y2 - r), (x2 + obj_w + r, y2 + r),
red, weight)
cv2.line(combo_image,
(x2 + obj_w - r, y2 + r), (x2 + obj_w + r, y2 - r),
red, weight)
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Do a sanity check on the discovered object
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
use_extracted = True # keep track of whether the extraction works or not
#check for size of the discovered result versus the original
scale_tolerance = 0.7
obj_area = polygon_area(object_corners_float)
obj_in_scene_area = polygon_area(obj_in_scene_corners_float)
area_min_allowed = obj_area * (1 - scale_tolerance) ** 2
area_max_allowed = obj_area * (1 + scale_tolerance) ** 2
if not (area_min_allowed < obj_in_scene_area < area_max_allowed):
print ('A homography was found but it seems too large or' \
' too small for a real match.')
use_extracted = False
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Extract the object from the original scene
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#max/min the corners to disentangle any flipped, etc. projections
tops_bottoms = list(corner[1] for corner in obj_in_scene_corners_float)
lefts_rights = list(corner[0] for corner in obj_in_scene_corners_float)
#limit the boundaries to the scene boundaries
top = max(int(min(tops_bottoms)), 0)
bottom = min(int(max(tops_bottoms)), scene_h - 1)
left = max(int(min(lefts_rights)), 0)
right = min(int(max(lefts_rights)), scene_w - 1)
extracted = scene_original[top:bottom, left:right]
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Display and save all the results
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
combo_path = path.join('.', 'output_images', 'match_visualization.png')
cv2.imwrite(combo_path, combo_image)
mini_combo_h, mini_combo_w = int(round(float(combo_image.shape[0])/2)),\
int(round(float(combo_image.shape[1])/2))
mini_combo = cv2.resize(combo_image, (mini_combo_w, mini_combo_h))
cv2.imshow('match visualization', mini_combo)
# only display/save extracted if the previous tests indicated it was realistic
if use_extracted:
extracted_path = path.join('.', 'output_images', 'extracted.png')
cv2.imwrite(extracted_path, extracted)
mini_extr_h, mini_extr_w = int(round(float(extracted.shape[0])/2)),\
int(round(float(extracted.shape[1])/2))
mini_extr = cv2.resize(extracted, (mini_extr_w, mini_extr_h))
cv2.imshow('extracted image', mini_extr)
cv2.waitKey()
cv2.destroyAllWindows()
原因:在cmd下python->import cv2就开始报错ImportError:检查opencv的安装,看来还没运行代码,刚开始import就报错了。原来是opencv_python的问题。
怀疑及解决方案:
Issue1:怀疑是电脑上安装的python3.6.5与Anaconda中的python3.7.0冲突,pip安装时(pip install opencv_python-3.4.5+contrib-cp37-cp37m-win_amd64.whl)没有识别对应的python。
解决办法:去掉python3.6.5的系统环境变量(D:\ProgramFiles\Python36),卸载opencv_python,重新安装opencv_python(pip install opencv_python-3.4.5+contrib-cp37-cp37m-win_amd64.whl),报错依旧
Issue2:怀疑电脑上的opencv_python版本低或文件破坏。
解决办法:重新下载了opencv_python-3.4.7+contrib-cp37-cp37m-win_amd64.whl,重新安装opencv_python(pip install opencv_python-3.4.7+contrib-cp37-cp37m-win_amd64.whl),报错依旧
Issue3:win+r打开windows命令窗口输入python显示的是python3.7.0,而在D盘文件夹下文件——>打开Windows PowerShell——>以管理员身份打开Windows PowerShell输入python显示的是python3.6.5(而我在Issue1时已经去掉python3.6.5的系统环境变量)
解决办法:把(D:\ProgramFiles\Python36)备份好后,卸载python3.6.5,报错依旧
Issue4:应该还是python多版本的问题。
解决办法:依次检查系统环境变量,看是否哪个包含了opencv3.6.5(因为近期使用CMake编译过opencv工程),还是没有找到,
最后在wang的用户变量中找到(D:\ProgramFiles\Python36;D:\ProgramFiles\Python36\Scripts\)去掉后
Issue5:怀疑是Anaconda的问题
解决办法:卸载重装,在重装安装opencv_python(pip install opencv_python-3.4.5+contrib-cp37-cp37m-win_amd64.whl),还是报错依旧。
Issue6:还是python多版本的问题
解决办法:最后在wang的用户变量中找到(D:\ProgramFiles\Python36;D:\ProgramFiles\Python36\Scripts\)去掉后,重新卸载后安装opencv_python(pip install opencv_python-3.4.5+contrib-cp37-cp37m-win_amd64.whl)win+r打开windows命令窗口输入python显示的是python3.7.0,然后输入import cv2 报错更改为ImportError: numpy.core.multiarray failed to import
Issue7:ImportError: numpy.core.multiarray failed to import,百度解决,是numpy版本过低的问题。
解决办法:更新numpy,使用:pip install -U numpy就可以更新numpy版本了。但是实验室网络太差,更新不成功,下载whl,(地址参看我的另一篇博客:Python入门之第三方模块安装——https://www.cnblogs.com/Alliswell-WP/p/PythonOfPipInstall.html),下载最新的与64版本(numpy-1.17.0+mkl-cp37-cp37m-win_amd64.whl)后,安装(pip install numpy-1.17.0+mkl-cp37-cp37m-win_amd64.whl),在cmd下import cv2不报错了,问题解决。
参看:ImportError: numpy.core.multiarray failed to import——https://www.cnblogs.com/catpainter/p/8645455.html
Issue8:Pycharm下测试?
import cv2 as cv
src = cv.imread("D:/Working/opencvimg/lena.jpg")
#cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
cv.imshow("imput image", src)
cv.waitKey(0)
cv.destroyAllWindows()
print('Hi,Python!')
解决办法:在pycharm上新建python工程->新建New Python File->粘贴上面的代码(更改图片的路径和名称),测试成功。
Issue9:Pycharm无法识别Python已安装的模块,如cv2(OpenCV)模块
解决办法:Pycharm的菜单 File | Settings | Settings窗口 | Project:XXXX | Project Interpreter项 | 窗口右侧 齿轮按钮点击 | Show All... | 然后依据上图提示打开“Interpreter Paths”窗口
将已安装的Python路径下的 Lib/site-packages 这个路径添加到“Interpreter Paths”窗口项中,最后保存
参看:本人另一篇博客:在cmd下可以import cv2,而Pycharm报错:找不到cv2 ——https://www.cnblogs.com/Alliswell-WP/p/Pycharm_cv2_issue.html
Issue10:测试brisk,报错:Traceback (most recent call last):
File "D:/Working/PycharmProjects/python_brisk_demo-master/brisk_demo.py", line 35, in
extractor = cv2.DescriptorExtractor_create('BRISK') # non-patented. Thank you!
AttributeError: module 'cv2.cv2' has no attribute 'DescriptorExtractor_create'
解决办法:网上说OpenCV3.4.3及之后版本下没有使用该算法的权限,所以重新下载安装
opencv-contrib-python 3.4.2.16
opencv-python 3.4.2.16
清华大学opencv Python库:https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple/opencv-python/
Issue11:安装完成仍报错:没有权限
解决办法:此算法没有权限,将下载代码时的_cv2_fallback文件夹下(__pycache__文件夹——__init__.cpython-37.pyc,__init__.py,cv2.pyd)替换C:\ProgramData\Anaconda3\Lib\site-packages\cv2下相应的文件,还要改名哦(一定要备份更改的文件,如果失败,可以恢复)!系统警告,点击“继续”。运行代码,报错依旧!
Issue12:操作完成仍报错:没有权限
解决办法:此算法没有权限,下载下面的BRISK算法,实现。更改路径和名称后,成功!
#!/usr/bin/env python
# _*_coding:utf-8 _*_
import cv2
# import numpy
def main():
img = cv2.imread("D:/Working/opencvimg/lena.jpg")
cv2.imshow('Input Image', img)
cv2.waitKey(0)
brisk = cv2.BRISK_create()
keypoints = brisk.detect(img, None)
# 必须要先初始化img2
img2 = img.copy()
img2 = cv2.drawKeypoints(img, keypoints,img2, color=(0, 255, 0))
cv2.imshow('Detected BRISK keypoints', img2)
cv2.waitKey(0)
if __name__ == '__main__':
main()
参考;1)OpenCV-Python Feature2D 特征点检测(含SIFT/SURF/ORB/KAZE/FAST/BRISK/AKAZE)——https://blog.csdn.net/amusi1994/article/details/79591205
2)[OpenCV-Python] OpenCV 中图像特征提取与描述 部分 V (二)——https://www.cnblogs.com/Undo-self-blog/p/8447771.html