大家好,我是第一次写CSDN博客,也是刚开始学习用Python进行计算机视觉编程,有很多不懂和不足的地方,希望大家多包涵。以下纯粹是我个人的一些实际操作经历。
在《Python计算机视觉编程》一书中,有关于增强现实AR的一部分编程程序。尤其是一段在相片上显示一个虚拟茶壶的程序,在网上(包括CSDN)有很多程序。这里我个人觉得这2篇文章算不错的,给出链接。第一个是https://blog.csdn.net/Dujing2019/article/details/91691202,第二个是https://blog.csdn.net/titansm/article/details/89057184。但直接使用这些程序,不一定能得到它们说的同样的效果和结果(至少我不是),所以我贴出自己的代码,以供大家参考。

1、一些基本的我就不说了,例如软件和包的安装等,大家参考以上两个链接和其他文章,这里我说点和其它文章不一样的地方。对了,我的环境是Win7 64位,装了anaconda3和python3.6。
2、首先是以上两个链接中都会提到的sift.process_image等等函数,你会发现文章中根本没细说这写函数的内容是什么。其实这些函数在《Python计算机视觉编程》一书中有详细提及,只是以上链接文章没提罢了,这里我把所有相关的程序待会在下面都列出来。
3、sift.process_image函数是将.bmp文件转变成.sift文件。那么如何转变呢?这里你需要下载一个vlfeat-0.9.20-bin.tar.gz压缩包(注意必须是0.9.20版本,0.9.21版本没用),解压缩后将其中/bin/win32中的sift.exe、vl.dll、vl.lib拷贝到和你这个AR python程序同一个文件夹下。很奇怪我是64位版本为什么用win32中的文件吧?其实我也奇怪,但我试过了,用win64根本不行,只有win32可以,我也不知道为什么。
4、另外,你在安装完PyOpenGL后,需要将OpenGL库文件(由于我安装了anaconda3,因此我的OpenGL库文件在Continuum\anaconda3\Lib\site-packages\OpenGL)下的DLLS文件夹中的部分东西删除,只保留gle_AUTHORS、gle_COPYING、gle_COPYING.src、gle64.vc14.dll、glut64.vc14.dll这六个文件即可。否则在编译函数draw_teapot时会跳出一个莫名其妙的错误。
5、这一点非常关键,我找遍了好多文章,最后终于在第二个链接中找到了,也就是width和height的值。一定不能用大多数文章里使用的1000和747,要用你自己那个.bmp的像素。比如我的.bmp文件的像素是553和369(可以点击右键–>属性–>详细信息看到该文件的像素)。
另外关于这一点,我做了若干次尝试:当width,height = 553,369时,效果OK;当width,height = 553,300时,效果也OK;当width不是553时,哪怕是554或552,出来的背景效果都是极度扭曲的。
还有,width和height的值不能太大,否则编译时就会报错,什么内存读取溢出或错误OSError: exception: access violation reading 0x0000000008FC7000。网上很多人说这是64位版本问题,算是一个bug,具体我也搞不清楚。所以你在生成.bmp图片时,就要记住图片像素值不能太大。
好,接下来我就贴代码了。

首先生成一个空文件sift.py,将它和其它AR python程序放在同一个文件夹。sift.py里的程序是:

from PIL import Image
from numpy import *
from pylab import *
import osdef process_image(imagename, resultname, params='--edge-thresh 10 --peak-thresh 5'):if imagename[-3:] != 'pgm':im = Image.open(imagename).convert('L')im.save('tmp.pgm')imagename = 'tmp.pgm'cmmd = str("sift " + imagename + " --output=" + resultname + " " + params)os.system(cmmd)print(str("processed " + imagename + " to " + resultname))def read_features_from_file(filename):f = loadtxt(filename)return (f[:, :4], f[:, 4:])def match(desc1,desc2):desc1 = array([d/linalg.norm(d) for d in desc1])desc2 = array([d/linalg.norm(d) for d in desc2])dist_ratio = 0.6desc1_size = desc1.shapematchscores = zeros((desc1_size[0],1),'int')desc2t = desc2.Tfor i in range(desc1_size[0]):dotprods = dot(desc1[i,:],desc2t)dotprods = 0.9999*dotprodsindx = argsort(arccos(dotprods))if arccos(dotprods)[indx[0]] < dist_ratio*arccos(dotprods)[indx[1]]:matchscores[i] = int(indx[0])return matchscoresdef match_twosided(desc1,desc2):matches_12 = match(desc1, desc2)matches_21 = match(desc2, desc1)ndx_12 = matches_12.nonzero()[0]for n in ndx_12:if matches_21[matches_12[n]] != n:matches_12[n] = 0return matches_12

然后生成一个空文件homography.py,将它和其它AR python程序放在同一个文件夹。homography.py里的程序是:

import os
from PIL import Image
from numpy import *
from pylab import *
from scipy import ndimage
import ransacdef make_homog(points):return vstack((points,ones((1,points.shape[1]))))class RansacModel(object):def __init__(self,debug=False):self.debug = debugdef fit(self,data):data = data.Tfp = data[:3,:4]tp = data[3:,:4]return H_from_points(fp,tp)def get_error(self,data,H):data = data.Tfp = data[:3]tp = data[3:]fp_transformed = dot(H,fp)for i in range(3):fp_transformed[i] /= fp_transformed[2]return sqrt(sum((tp-fp_transformed)**2,axis=0))def H_from_ransac(fp,tp,model,maxiter=1000,match_threshold=10):data = vstack((fp,tp))H,ransac_data = ransac.ransac(data.T,model,4,maxiter,match_threshold,10,return_all=True)return H,ransac_data['inliers']

再生成一个空文件ransac.py,将它和其它AR python程序放在同一个文件夹。ransac.py里的程序是(ransac.py其实网上能下载,这里我把代码都贴出来吧):

import numpy
import scipy # use numpy if scipy unavailable
import scipy.linalg # use numpy if scipy unavailable## Copyright (c) 2004-2007, Andrew D. Straw. All rights reserved.## Redistribution and use in source and binary forms, with or without
## modification, are permitted provided that the following conditions are
## met:##     * Redistributions of source code must retain the above copyright
##       notice, this list of conditions and the following disclaimer.##     * Redistributions in binary form must reproduce the above
##       copyright notice, this list of conditions and the following
##       disclaimer in the documentation and/or other materials provided
##       with the distribution.##     * Neither the name of the Andrew D. Straw nor the names of its
##       contributors may be used to endorse or promote products derived
##       from this software without specific prior written permission.## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.def ransac(data,model,n,k,t,d,debug=False,return_all=False):"""fit model parameters to data using the RANSAC algorithmThis implementation written from pseudocode found at
http://en.wikipedia.org/w/index.php?title=RANSAC&oldid=116358182{{{
Given:data - a set of observed data pointsmodel - a model that can be fitted to data pointsn - the minimum number of data values required to fit the modelk - the maximum number of iterations allowed in the algorithmt - a threshold value for determining when a data point fits a modeld - the number of close data values required to assert that a model fits well to data
Return:bestfit - model parameters which best fit the data (or nil if no good model is found)
iterations = 0
bestfit = nil
besterr = something really large
while iterations < k {maybeinliers = n randomly selected values from datamaybemodel = model parameters fitted to maybeinliersalsoinliers = empty setfor every point in data not in maybeinliers {if point fits maybemodel with an error smaller than tadd point to alsoinliers}if the number of elements in alsoinliers is > d {% this implies that we may have found a good model% now test how good it isbettermodel = model parameters fitted to all points in maybeinliers and alsoinliersthiserr = a measure of how well model fits these pointsif thiserr < besterr {bestfit = bettermodelbesterr = thiserr}}increment iterations
}
return bestfit
}}}
"""iterations = 0bestfit = Nonebesterr = numpy.infbest_inlier_idxs = Nonewhile iterations < k:maybe_idxs, test_idxs = random_partition(n,data.shape[0])maybeinliers = data[maybe_idxs,:]test_points = data[test_idxs]maybemodel = model.fit(maybeinliers)test_err = model.get_error( test_points, maybemodel)also_idxs = test_idxs[test_err < t] # select indices of rows with accepted pointsalsoinliers = data[also_idxs,:]if debug:'''print 'test_err.min()',test_err.min()print 'test_err.max()',test_err.max()print 'numpy.mean(test_err)',numpy.mean(test_err)print 'iteration %d:len(alsoinliers) = %d'%(iterations,len(alsoinliers))'''if len(alsoinliers) > d:betterdata = numpy.concatenate( (maybeinliers, alsoinliers) )bettermodel = model.fit(betterdata)better_errs = model.get_error( betterdata, bettermodel)thiserr = numpy.mean( better_errs )if thiserr < besterr:bestfit = bettermodelbesterr = thiserrbest_inlier_idxs = numpy.concatenate( (maybe_idxs, also_idxs) )iterations+=1if bestfit is None:raise ValueError("did not meet fit acceptance criteria")if return_all:return bestfit, {'inliers':best_inlier_idxs}else:return bestfitdef random_partition(n,n_data):"""return n random rows of data (and also the other len(data)-n rows)"""all_idxs = numpy.arange( n_data )numpy.random.shuffle(all_idxs)idxs1 = all_idxs[:n]idxs2 = all_idxs[n:]return idxs1, idxs2class LinearLeastSquaresModel:"""linear system solved using linear least squaresThis class serves as an example that fulfills the model interfaceneeded by the ransac() function."""def __init__(self,input_columns,output_columns,debug=False):self.input_columns = input_columnsself.output_columns = output_columnsself.debug = debugdef fit(self, data):A = numpy.vstack([data[:,i] for i in self.input_columns]).TB = numpy.vstack([data[:,i] for i in self.output_columns]).Tx,resids,rank,s = scipy.linalg.lstsq(A,B)return xdef get_error( self, data, model):A = numpy.vstack([data[:,i] for i in self.input_columns]).TB = numpy.vstack([data[:,i] for i in self.output_columns]).TB_fit = scipy.dot(A,model)err_per_point = numpy.sum((B-B_fit)**2,axis=1) # sum squared error per rowreturn err_per_pointdef test():# generate perfect input datan_samples = 500n_inputs = 1n_outputs = 1A_exact = 20*numpy.random.random((n_samples,n_inputs) )perfect_fit = 60*numpy.random.normal(size=(n_inputs,n_outputs) ) # the modelB_exact = scipy.dot(A_exact,perfect_fit)assert B_exact.shape == (n_samples,n_outputs)# add a little gaussian noise (linear least squares alone should handle this well)A_noisy = A_exact + numpy.random.normal(size=A_exact.shape )B_noisy = B_exact + numpy.random.normal(size=B_exact.shape )if 1:# add some outliersn_outliers = 100all_idxs = numpy.arange( A_noisy.shape[0] )numpy.random.shuffle(all_idxs)outlier_idxs = all_idxs[:n_outliers]non_outlier_idxs = all_idxs[n_outliers:]A_noisy[outlier_idxs] =  20*numpy.random.random((n_outliers,n_inputs) )B_noisy[outlier_idxs] = 50*numpy.random.normal(size=(n_outliers,n_outputs) )# setup modelall_data = numpy.hstack( (A_noisy,B_noisy) )input_columns = range(n_inputs) # the first columns of the arrayoutput_columns = [n_inputs+i for i in range(n_outputs)] # the last columns of the arraydebug = Falsemodel = LinearLeastSquaresModel(input_columns,output_columns,debug=debug)linear_fit,resids,rank,s = scipy.linalg.lstsq(all_data[:,input_columns],all_data[:,output_columns])# run RANSAC algorithmransac_fit, ransac_data = ransac(all_data,model,50, 1000, 7e3, 300, # misc. parametersdebug=debug,return_all=True)if 1:import pylabsort_idxs = numpy.argsort(A_exact[:,0])A_col0_sorted = A_exact[sort_idxs] # maintain as rank-2 arrayif 1:pylab.plot( A_noisy[:,0], B_noisy[:,0], 'k.', label='data' )pylab.plot( A_noisy[ransac_data['inliers'],0], B_noisy[ransac_data['inliers'],0], 'bx', label='RANSAC data' )else:pylab.plot( A_noisy[non_outlier_idxs,0], B_noisy[non_outlier_idxs,0], 'k.', label='noisy data' )pylab.plot( A_noisy[outlier_idxs,0], B_noisy[outlier_idxs,0], 'r.', label='outlier data' )pylab.plot( A_col0_sorted[:,0],numpy.dot(A_col0_sorted,ransac_fit)[:,0],label='RANSAC fit' )pylab.plot( A_col0_sorted[:,0],numpy.dot(A_col0_sorted,perfect_fit)[:,0],label='exact system' )pylab.plot( A_col0_sorted[:,0],numpy.dot(A_col0_sorted,linear_fit)[:,0],label='linear fit' )pylab.legend()pylab.show()if __name__=='__main__':test()

接下来是主程序了。生成一个空文件AR_Test.py,将它和其它AR python程序放在同一个文件夹。AR_Test.py里的程序是(这里基本就是直接复制黏贴链接一和链接二了):

from pylab import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import pygame, pygame.image
from pygame.locals import *
from numpy import *
import homography,camera,sift
import math
from PIL import Imagedef cube_points(c, wid):p = []# bottomp.append([c[0]-wid, c[1]-wid, c[2]-wid])p.append([c[0]-wid, c[1]+wid, c[2]-wid])p.append([c[0]+wid, c[1]+wid, c[2]-wid])p.append([c[0]+wid, c[1]-wid, c[2]-wid])p.append([c[0]-wid, c[1]-wid, c[2]-wid]) #same as first to close plot# topp.append([c[0]-wid, c[1]-wid, c[2]+wid])p.append([c[0]-wid, c[1]+wid, c[2]+wid])p.append([c[0]+wid, c[1]+wid, c[2]+wid])p.append([c[0]+wid, c[1]-wid, c[2]+wid])p.append([c[0]-wid, c[1]-wid, c[2]+wid]) #same as first to close plot# vertical sidesp.append([c[0]-wid, c[1]-wid, c[2]+wid])p.append([c[0]-wid, c[1]+wid, c[2]+wid])p.append([c[0]-wid, c[1]+wid, c[2]-wid])p.append([c[0]+wid, c[1]+wid, c[2]-wid])p.append([c[0]+wid, c[1]+wid, c[2]+wid])p.append([c[0]+wid, c[1]-wid, c[2]+wid])p.append([c[0]+wid, c[1]-wid, c[2]-wid])return array(p).Tdef my_calibration(sz):row, col = szfx = 2555*col/2592fy = 2586*row/1936K = diag([fx, fy, 1])K[0, 2] = 0.5*colK[1, 2] = 0.5*rowreturn Kdef set_projection_from_camera(K):  # 获取视图glMatrixMode(GL_PROJECTION)glLoadIdentity()fx = K[0, 0]fy = K[1, 1]fovy = 2 * math.atan(0.5 * height / fy) * 180 / math.piaspect = (width * fy) / (height * fx)# 定义近和远的剪裁平面near = 0.1far = 100.0# 设定透视gluPerspective(fovy, aspect, near, far)glViewport(0, 0, width, height)def set_modelview_from_camera(Rt):  # 获取矩阵glMatrixMode(GL_MODELVIEW)glLoadIdentity()# 围绕x轴将茶壶旋转90度,使z轴向上Rx = np.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]])# 获得旋转的最佳逼近R = Rt[:, :3]U, S, V = np.linalg.svd(R)R = np.dot(U, V)R[0, :] = -R[0, :]  # 改变x轴的符号# 获得平移量t = Rt[:, 3]# 获得4*4的的模拟视图矩阵M = np.eye(4)M[:3, :3] = np.dot(R, Rx)M[:3, 3] = t# 转置并压平以获取列序数值M = M.Tm = M.flatten()# 将模拟视图矩阵替换成新的矩阵glLoadMatrixf(m)def draw_background(imname):# 载入背景图像bg_image = pygame.image.load(imname).convert()bg_data = pygame.image.tostring(bg_image, 'RGBX', 1)  # 将图像转为字符串描述glMatrixMode(GL_MODELVIEW)  # 将当前矩阵指定为投影矩阵glLoadIdentity()  # 把矩阵设为单位矩阵#glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)  # 清楚颜色、深度缓冲glEnable(GL_TEXTURE_2D)  # 纹理映射glBindTexture(GL_TEXTURE_2D, glGenTextures(1))glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, bg_data)#glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)# 绑定纹理glBegin(GL_QUADS)glTexCoord2f(0.0, 0.0);glVertex3f(-1.0, -1.0, -1.0)glTexCoord2f(1.0, 0.0);glVertex3f(1.0, -1.0, -1.0)glTexCoord2f(1.0, 1.0);glVertex3f(1.0, 1.0, -1.0)glTexCoord2f(0.0, 1.0);glVertex3f(-1.0, 1.0, -1.0)glEnd()glDeleteTextures(1)  # 清除纹理def draw_teapot(size):  # 红色茶壶glEnable(GL_LIGHTING)glEnable(GL_LIGHT0)glEnable(GL_DEPTH_TEST)glClear(GL_DEPTH_BUFFER_BIT)# 绘制红色茶壶glMaterialfv(GL_FRONT, GL_AMBIENT, [0, 0, 0, 0])glMaterialfv(GL_FRONT, GL_DIFFUSE, [0.5, 0.0, 0.0, 0.0])glMaterialfv(GL_FRONT, GL_SPECULAR, [0.7, 0.6, 0.6, 0.0])glMaterialf(GL_FRONT, GL_SHININESS, 0.25 * 128.0)glutSolidTeapot(size)def drawFunc(size):  # 白色茶壶glRotatef(0.5, 5, 5, 0)  # (角度,x,y,z)glutWireTeapot(size)# 刷新显示glFlush()def load_and_draw_model(filename):glEnable(GL_LIGHTING)glEnable(GL_LIGHT0)glEnable(GL_DEPTH_TEST)glClear(GL_DEPTH_BUFFER_BIT)glMaterialfv(GL_FRONT,GL_AMBIENT,[0,0,0,0])glMaterialfv(GL_FRONT, GL_DIFFUSE, [0.5, 0.75, 1.0, 0.0])glMaterialf(GL_FRONT, GL_SHININESS, 0.25*128.0)import objloaderobj = objloader.OBJ(filename,swapyz=True)glCallList(obj.gl_list)#这里一定要是.bmp图片的分辨率,不要迷信网上的1000,747
width,height = 553,369
def setup():pygame.init()pygame.display.set_mode((width,height),OPENGL | DOUBLEBUF)pygame.display.set_caption("OpenGL AR demo")# 计算特征,先对着一本书竖着排一张book0.jpg,再对着这本书横着拍一张book1.jpg
sift.process_image('book0.jpg', 'im0.sift')
l0, d0 = sift.read_features_from_file('im0.sift')
sift.process_image('book1.jpg', 'im1.sift')
l1, d1 = sift.read_features_from_file('im1.sift')# 匹配特征,计算单应性矩阵
matches = sift.match_twosided(d0, d1)
ndx = matches.nonzero()[0]
fp = homography.make_homog(l0[ndx, :2].T)
ndx2 = [int(matches[i]) for i in ndx]
tp = homography.make_homog(l1[ndx2, :2].T)model = homography.RansacModel()
H, inliers = homography.H_from_ransac(fp, tp, model)# 计算照相机标定矩阵
K = my_calibration((height, width))
# 位于边长为0.2,z=0平面上的三维点
box = cube_points([0, 0, 0.1], 0.1)# 投影第一幅图下个上底部的正方形
cam1 = camera.Camera(hstack((K, dot(K, array([[0], [0], [-1]])))))
# 底部正方形上的点
box_cam1 = cam1.project(homography.make_homog(box[:, :5]))# 使用H将点变换到第二幅图像中
box_trans = homography.normalize(dot(H, box_cam1))# 从cam1和H中计算第二个照相机矩阵
cam2 = camera.Camera(dot(H, cam1.P))
A = dot(linalg.inv(K), cam2.P[:, :3])
A = array([A[:, 0], A[:, 1], cross(A[:, 0], A[:, 1])]).T
cam2.P[:, :3] = dot(K, A)
# 使用第二个照相机矩阵投影
box_cam2 = cam2.project(homography.make_homog(box))#这一段程序是在book图上画一个AR立方体
point = array([1,1,0,1]).T
print(homography.normalize(dot(dot(H,cam1.P),point)))
print(cam2.project(point))
im0 = array(Image.open('book0.jpg'))
im1 = array(Image.open('book1.jpg'))
figure()
imshow(im0)
plot(box_cam1[0,:],box_cam1[1,:],linewidth=3)
figure()
imshow(im1)
plot(box_trans[0,:],box_trans[1,:],linewidth=3)
figure()
imshow(im1)
plot(box_cam2[0,:],box_cam2[1,:],linewidth=3)
show()Rt = dot(linalg.inv(K),cam2.P)
setup()
draw_background("book1.bmp")
set_projection_from_camera(K)
set_modelview_from_camera(Rt)
draw_teapot(0.1)
#drawFunc(0.1)pygame.display.flip()
while True:for event in pygame.event.get():if event.type==pygame.QUIT:sys.exit()

好,到这里基本结束了。第一次写CSDN博客,不足之处还望大家海涵。希望对你有帮助!

《Python计算机视觉编程》一书中关于增强现实茶壶显示的程序相关推荐

  1. 四、【python计算机视觉编程】照相机模型与增强现实

    照相机模型与增强现实 (一)针孔照相机模型 (1)照相机矩阵 (2)三维点的投影 (3)照相机矩阵的分解 (4)计算照相机中心 (二)照相机标定 (三)以平面和标记物进行姿态估计 (四)增强现实 (A ...

  2. Python计算机视觉编程第四章——照相机模型与增强现实

    Python计算机视觉编程 照相机模型与增强现实 (一)针孔照相机模型 1.1 照相机矩阵 1.2 三维点的投影 1.3 照相机矩阵的分解 1.4 计算照相机中心 (二)照相机标定 (三)以平面和标记 ...

  3. 计算机视觉要学哪些编程语言,Python计算机视觉编程

    Python计算机视觉编程 语音 编辑 锁定 讨论 上传视频 <Python计算机视觉编程>是由2014年6月1日人民邮电出版社出版的图书,作者是[瑞典] Jan Erik Solem [ ...

  4. 《Python计算机视觉编程》

    <Python计算机视觉编程> 基本信息 作者: (美)Jan Erik Solem 译者: 朱文涛 袁勇 丛书名: 图灵程序设计丛书 出版社:人民邮电出版社 ISBN:978711535 ...

  5. 大数据、人工智能学习书籍推荐——Python计算机视觉编程

    [前言] 本文首发于:泰泰博客--Python计算机视觉编程,大数据.人工智能学习书籍. 今天给大家推荐一本好书--Python计算机视觉编程.如果你在寻找关于大数据相关的学习书籍或准备"进 ...

  6. python计算机视觉编程——基本的图像操作和处理

    python计算机视觉编程--第一章(基本的图像操作和处理) 第1章 基本的图像操作和处理 1.1 PIL:Python图像处理类库 1.1.1 转换图像格式--save()函数 1.1.2 创建缩略 ...

  7. python计算机视觉编程——立体图像之计算视差图

    计算视差图 一.立体图像 1.1概念 1.2关于图像配准算法 二.立体重建之计算视差图 2.1归一化及算法概念 2.2匹配流程 三.实验测试 3.1实验要求 3.2实验代码 3.3实验结果分析 3.4 ...

  8. Python计算机视觉编程第二章——局部图像描述子

    Python计算机视觉编程 局部图像描述子 (一)Harris 角点检测器 (二)SIFT(尺度不变特征变换) 2.1 兴趣点 2.2 描述子 2.3 检测兴趣点 2.4 匹配描述子 (三)匹配地理标 ...

  9. python计算机视觉编程——基于BOF的图像检索(附代码)

    图像检索 一.图像检索 1.1基本原理 1.2 BOW原理简述(同BOF原理) 1.3 基于BOF的图像检索基本流程 1.3.1 sift特征提取 1.3.2 建立视觉单词 1.3.3 K-Means ...

最新文章

  1. 【论文速读】基于投影方法的激光雷达点云处理比较
  2. 再放QQ微博邀请码(2)
  3. 如果你也时常想要上进,我们可以相互鼓励,相互促进
  4. SQL SERVER2005加密解密数据
  5. 原来医生的处方不是随便乱写的...
  6. python自动解析json_Python语言解析JSON详解
  7. jquery中的 $(function(){})
  8. 编码 括号_Java编码规范整理汇总
  9. js使用showModalDialog,弹出一个自适应大小窗口
  10. 未能正确加载“ProviderPackage”包。
  11. 驱动开发——经典图书免费试读下载及勘误讨论
  12. 国内外3D视觉优秀的实验室或者团队汇总
  13. AI实战:推荐系统之影视领域用户画像——标签数据清洗
  14. snagit 注册码
  15. NVIDIA Jetson Xavier NX 安yolo v5 +D435i摄像头 pyrealsense2 亲测好用
  16. iOS上线 ERROR ITMS-4238
  17. Linux 修改系统时间为东八区时间
  18. 【活动报名】 拥抱公平《 Impact Tech, She Can 》
  19. RewriteCond %{REQUEST_URI}
  20. Python 两种csv文件的写入方式

热门文章

  1. :before、:after伪元素的用法 !
  2. php echo,print,print_r,var_dum的区别
  3. char(10)和nchar(10)的区别
  4. “秋天的第一杯奶茶”突然刷屏!这是什么新梗?
  5. [英文邮件] 表达感谢的话 + 回复别人的祝福
  6. 老调重弹--自建blog网站
  7. 第十二届蓝桥杯初赛试题B直线
  8. 项目总估值从70亿到150多亿,成功运营首期的腾讯AI加速器正招募第二期
  9. 获取当前目录下的所有文件夹
  10. shell获取当前目录和当前文件名和当前目录的路径