实例介绍
【实例简介】行人检测与轨迹追踪.py
行人检测追踪系统利用OpenCV中预先训练好的HOG 线性SVM模型(也可自己训练HOG 线性SVM模型)对视频中的行人进行检测,利用追踪算法绘制出行人的移动轨迹。整个系统用python实现,并用wxpython实现了GUI。
【实例截图】
【核心代码】
# -*- coding: utf-8 -*-
"""
Created on Wed Mar 29 11:04:22 2017
@author: Eric Liuwch
"""
from __future__ import print_function
from imutils.object_detection import non_max_suppression
import numpy as np
import datetime
import imutils
import wx
import cv2
import cv2.cv as cv
from PIL import Image
import matplotlib
# matplotlib采用WXAgg为后台,将matplotlib嵌入wxPython中
matplotlib.use("WXAgg")
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
from matplotlib.ticker import MultipleLocator, FuncFormatter
from matplotlib.font_manager import FontProperties
from skimage import data,exposure
font_set = FontProperties(fname=r"c:\windows\fonts\simsun.ttc", size=15)
import matplotlib.pyplot as plt
######################################################################################
class MPL_Panel_base(wx.Panel):
''''' #MPL_Panel_base背景面板,可以继承或者创建实例'''
def __init__(self,parent):
wx.Panel.__init__(self,parent=parent, id=-1)
self.max_width = 400
self.max_height = 600
self.MinScale=2000
self.MaxScale=20000
self.MinContourArea=100
self.MaxContourArea=10000
self.flag1=True
self.flag2=True
self.flag3=True
self.flag4=True
self.flag5=True
self.flag6=True
self.Figure=plt.figure(figsize=(3,3)) # figsize(单位:英寸)不能太大,会压缩空白位图,使其无法显示
self.subplot = self.Figure.add_subplot(3,2,1)
self.subplot1 = self.Figure.add_subplot(3,2,2)
self.subplot2 = self.Figure.add_subplot(3,2,3)
self.subplot3 = self.Figure.add_subplot(3,2,4)
self.subplot2 = self.Figure.add_subplot(3,2,5)
self.subplot3 = self.Figure.add_subplot(3,2,6)
self.FigureCanvas = FigureCanvas(self,-1,self.Figure)
self.NavigationToolbar = NavigationToolbar(self.FigureCanvas)
self.StaticText = wx.StaticText(self,-1,label='Show Help String')
self.SubBoxSizer = wx.BoxSizer(wx.HORIZONTAL)
self.SubBoxSizer.Add(self.NavigationToolbar,proportion =0, border = 5,flag = wx.ALL | wx.EXPAND)
self.SubBoxSizer.Add(self.StaticText,proportion =1, border = 5,flag = wx.ALL | wx.EXPAND)
self.SubBoxSizer1 = wx.BoxSizer(wx.HORIZONTAL)
self.SubBoxSizer1.Add(self.FigureCanvas,proportion =-5, border = 12,flag = wx.ALL | wx.EXPAND)
self.TopBoxSizer = wx.BoxSizer(wx.VERTICAL)
self.TopBoxSizer.Add(self.SubBoxSizer,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND)
self.TopBoxSizer.Add(self.SubBoxSizer1,proportion =-5, border = 2,flag = wx.ALL | wx.EXPAND)
self.SetSizer(self.TopBoxSizer)
###方便调用
self.plt=plt
def plotImage111(self, path):
uipath = unicode(path, "utf8")
img=Image.open(uipath)
self.plt.subplot(1,1,1)
self.plt.axis('off')
self.plt.imshow(img)
def plotVideo111(self, path):
cap = cv2.VideoCapture(path.encode('gbk'))
for i in range(50):
ret, frame = cap.read()
if ret==True:
self.cla()
self.plt.subplot(1,1,1)
self.plt.imshow(frame)
self.plt.axis('off')
self.UpdatePlot()
cap.release()
cv2.destroyAllWindows()
def plotImage121(self, path):
img=Image.open(path)
self.plt.subplot(1,2,1)
self.plt.imshow(img)
def PlotImage122(self, path):
img=Image.open(path)
self.plt.subplot(1,2,2)
self.plt.imshow(img)
def PlotImage211(self, path):
img=Image.open(path)
self.plt.subplot(2,1,1)
self.plt.imshow(img)
def PlotImage212(self, path):
img=Image.open(path)
self.plt.subplot(2,1,2)
self.plt.imshow(img)
def PlotImage221(self, path):
img=Image.open(path)
self.plt.subplot(2,2,1)
self.plt.imshow(img)
def PlotImage222(self, path):
img=Image.open(path)
self.plt.subplot(2,2,2)
self.plt.imshow(img)
def PlotImage223(self, path):
img=Image.open(path)
self.plt.subplot(2,2,3)
self.plt.imshow(img)
def PlotImage224(self, path):
img=Image.open(path)
self.plt.subplot(2,2,4)
self.plt.imshow(img)
def Exit(self):
self.flag1=False
self.flag2=False
self.flag3=False
self.flag4=False
self.flag5=False
self.flag6=False
def GetSize(self, img):
height, width = img.shape[:2]
if width>self.max_width:
height = height*self.max_width/width
width = self.max_width
if height>self.max_height:
width = width*self.max_height/height
height = self.max_height
size = width, height
return size
def ScaleImage(self, path):
source = cv2.imread(path.encode('gbk'),cv2.CV_LOAD_IMAGE_COLOR)
size= self.GetSize(source)
res = cv2.resize(source,size, interpolation = cv2.INTER_CUBIC) #利用opencv做的图像压缩
img = cv2.cvtColor(np.uint8(res), cv2.cv.CV_BGR2RGB)
cv2.imwrite(frame.ObjPath, img)
def ShowVideo(self, path):
cap = cv2.VideoCapture(path.encode('gbk'))
while(cap.isOpened()):
ret, frame = cap.read()
#gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
if ret==True:
cv2.imshow('video',frame)
else:
break
if cv2.waitKey(1) & self.flag1==False:
break
cap.release()
cv2.destroyAllWindows()
def OpencvCanny(self, path):
cap = cv2.VideoCapture(path.encode('gbk'))
while(cap.isOpened()):
ret, frame = cap.read()
#gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
if ret==True:
img = cv2.GaussianBlur(frame,(3,3),0)
canny = cv2.Canny(img, 50, 150)
cv2.namedWindow('frame',0)#通过指定的名字,创建一个可以作为图像和进度条的容器窗口
cv2.namedWindow('canny',0)#通过指定的名字,创建一个可以作为图像和进度条的容器窗口
cv2.resizeWindow('frame',640,480)
cv2.resizeWindow('canny',640,480)
cv2.imshow('frame',frame)
cv2.imshow('canny',canny)
else:
break
if cv2.waitKey(1) & self.flag2==False:
break
cap.release()
cv2.destroyAllWindows()
def OpencvCaptureMoveTarget(self, path):
camera = cv2.VideoCapture(path.encode('gbk'))
if not camera.isOpened():
camera = cv2.VideoCapture(0)
firstFrame = None
while True:
(grabbed, frame) = camera.read()
# if could not grab ,is end of the frame
if not grabbed:
break
# resize scale and GaussianBlur
frame = imutils.resize(frame, width=500)
orig = frame.copy()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (21, 21), 0)
# initial
if firstFrame is None:
firstFrame = gray
continue
# compute the difference of the current frame to the firstframe
frameDelta = cv2.absdiff(firstFrame, gray)
thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]
# dilate the threshing image
thresh = cv2.dilate(thresh, None, iterations=2)
(cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
# choose every contours
rects = []
for c in cnts:
# if the contour is too small, ignore it
if cv2.contourArea(c) < cv2.getTrackbarPos('Min','Capture move target'):
continue
# compute the bounding box for the contour, draw it on the frame,and update the text
(x, y, w, h) = cv2.boundingRect(c)
cv2.rectangle(orig, (x, y), (x w, y h), (0, 255, 0), 2)
rects.append((x, y, x w, y h))
#transform to array
rects = np.array(rects)
#apply non-maxima suppression to the bounding boxes
pick = non_max_suppression(rects, probs=None, overlapThresh=0.65)
# draw the final bounding boxes
for (xA, yA, xB, yB) in pick:
cv2.rectangle(frame, (xA, yA), (xB, yB), (0, 255, 0), 2)
cv2.putText(frame, "Contour Size: {}".format(cv2.getTrackbarPos('Min','Capture move target')), (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(frame, datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"),
(10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)
cv2.imshow("Before NMS", orig)
cv2.imshow("Capture move target", frame)
if cv2.waitKey(1) & self.flag3==False:
break
camera.release()
cv2.destroyAllWindows()
def OpencvCaptureMovePerson(self, path):
camera = cv2.VideoCapture(path.encode('gbk'))
(grabbed, frame) = camera.read()
fps = camera.get(cv2.cv.CV_CAP_PROP_FPS)
if not camera.isOpened():
camera = cv2.VideoCapture(0)
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())
prev_points = []
curr_points = []
nbFrames=0
frame = imutils.resize(frame, width=min(750, frame.shape[1]))
out = cv2.VideoWriter('C:\Users\hp\Videos\Capturesoutput.avi',-1, fps,(frame.shape[1],frame.shape[0]))#size必须与frame的size保持一致
while True:
nbFrames = 1
if (nbFrames%cv2.getTrackbarPos('Min','Capture person'))!=0:
continue
# 获取当前帧并初始化occupied/unoccupied文本
(grabbed, frame) = camera.read()
# 如果不能抓取到一帧,说明我们到了视频的结尾
if not grabbed:
break
# load the image and resize it to (1) reduce detection time
# and (2) improve detection accuracy
frame = imutils.resize(frame, width=min(750, frame.shape[1]))
# detect people in the image
(rects, weights) = hog.detectMultiScale(frame, winStride=(4, 4),
padding=(0, 0), scale=1.5)
# apply non-maxima suppression to the bounding boxes using a
# fairly large overlap threshold to try to maintain overlapping
# boxes that are still people
rects = np.array([[x, y, x w, y h] for (x, y, w, h) in rects])
pick = non_max_suppression(rects, probs=None, overlapThresh=0.65)
# draw the final bounding boxes
for (xA, yA, xB, yB) in pick:
cv2.rectangle(frame, (xA, yA), (xB, yB), (0, 255, 0), 2)
point= (int((xA xB)/2),int((yA yB)/2))
curr_points.append(point) #Add the new points to list
if len(curr_points)==len(prev_points):
for i in range(len(curr_points)):
cv2.line(frame, prev_points[i], curr_points[i], (255, 255, ),2)
prev_points= curr_points
if len (rects)==0:
prev_points = []
curr_points = []
# draw the text and timestamp on the frame
cv2.putText(frame, "Frame intervals : {}".format(cv2.getTrackbarPos('Min','Capture person')), (10, 20),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
cv2.putText(frame, datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"),
(10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)
# show the output images
cv2.imshow("Capture person", frame)
out.write(frame)
if cv2.waitKey(1) & self.flag2==False:
break
camera.release()
out.release()
cv2.destroyAllWindows()
def ShowCamera(self):
cap = cv2.VideoCapture(0)
fourcc = cv2.cv.CV_FOURCC(*'XVID')
#opencv3的话用:fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('C:\Users\hp\Videos\Captures\Camera.avi',fourcc,20.0,(640,480))#保存视频
while True:
ret,frame = cap.read()
#gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
out.write(frame)#写入视频
img = cv2.GaussianBlur(frame,(3,3),0)
canny = cv2.Canny(img, 50, 150)
cv2.imshow('frame',frame)#一个窗口用以显示原视频
cv2.imshow('gray',canny)#另一窗口显示处理视频
if cv2.waitKey(1) &self.flag3==False:
break
cap.release()
out.release()
cv2.destroyAllWindows()
def UpdatePlot(self):
'''''#修改图形的任何属性后都必须使用self.UpdatePlot()更新GUI界面 '''
self.FigureCanvas.draw()
self.Figure.images
def plot1(self,arr):
'''''#柱状图绘图命令plot1 '''
self.plt.subplot(2,2,2)
n, bins, patches=self.plt.hist(arr, bins=256, normed=1, facecolor='green', alpha=0.75)
self.UpdatePlot()
def plot2(self,arr):
'''''#柱状图绘图命令plot2 '''
self.plt.subplot(2,2,4)
n, bins, patches=self.plt.hist(arr, bins=256, normed=1, facecolor='green', alpha=0.75)
self.UpdatePlot()
def savefig(self,*args,**kwargs):
''''' #保存图形到文件 '''
self.Figure.savefig(*args,**kwargs)
def cla(self):
''''' # 再次画图前,必须调用该命令清空原来的图形 '''
self.Figure.clear()
self.Figure.set_canvas(self.FigureCanvas)
self.UpdatePlot()
def ShowHelpString(self,HelpString="Show Help String"):
''''' #可以用它来显示一些帮助信息,如鼠标位置等 '''
self.StaticText.SetLabel(HelpString)
def nothing(self,x):
self.flag2=False
self.flag2=True
self.OpencvCaptureMovePerson(frame.path)
###############################################################################
# MPL_Frame添加了MPL_Panel的1个实例
###############################################################################
class MPL_Frame(wx.Frame):
"""MPL_Frame可以继承,并可修改,或者直接使用"""
def __init__(self,title=u"行人检测追踪",size=(800,500)):
wx.Frame.__init__(self,parent=None,title = title,size=size)
self.MPL = MPL_Panel_base(self)
self.path = 'C:\Users\hp\Pictures\Saved Pictures\背景.jpg'
self.ObjPath = 'C:\Python Scripts\imageprocess\ObjImage.jpg'
#创建FlexGridSizer
self.FlexGridSizer=wx.FlexGridSizer( rows=9, cols=1, vgap=5,hgap=5)
self.FlexGridSizer.SetFlexibleDirection(wx.BOTH)
self.RightPanel = wx.Panel(self,-1)
#测试按钮1
self.Button1 = wx.Button(self.RightPanel,-1,u"文件打开",size=(100,40),pos=(10,10))
self.Button1.Bind(wx.EVT_BUTTON,self.Button1Event)
#测试按钮2
self.Button2 = wx.Button(self.RightPanel,-1,u"播放视频",size=(100,40),pos=(10,10))
self.Button2.Bind(wx.EVT_BUTTON,self.Button2Event)
#测试按钮3
self.Button3 = wx.Button(self.RightPanel,-1,u"行人检测追踪",size=(100,40),pos=(10,10))
self.Button3.Bind(wx.EVT_BUTTON,self.Button3Event)
#测试按钮4
self.Button4 = wx.Button(self.RightPanel,-1,u"退出",size=(100,40),pos=(10,10))
self.Button4.Bind(wx.EVT_BUTTON,self.Button4Event)
#加入Sizer中
self.FlexGridSizer.Add(self.Button1,proportion =0, border = 5,flag = wx.ALL | wx.EXPAND)
self.FlexGridSizer.Add(self.Button2,proportion =0, border = 5,flag = wx.ALL | wx.EXPAND)
self.FlexGridSizer.Add(self.Button3,proportion =0, border = 5,flag = wx.ALL | wx.EXPAND)
self.FlexGridSizer.Add(self.Button4,proportion =0, border = 5,flag = wx.ALL | wx.EXPAND)
self.RightPanel.SetSizer(self.FlexGridSizer)
self.BoxSizer=wx.BoxSizer(wx.HORIZONTAL)
self.BoxSizer.Add(self.MPL,proportion =-10, border = 2,flag = wx.ALL | wx.EXPAND)
self.BoxSizer.Add(self.RightPanel,proportion =0, border = 2,flag = wx.ALL | wx.EXPAND)
self.SetSizer(self.BoxSizer)
#状态栏
self.StatusBar()
#MPL_Frame界面居中显示
self.Centre(wx.BOTH)
#按钮事件,用于测试
def Button1Event(self,event):
self.MPL.flag1=False
self.MPL.flag2=False
self.MPL.flag3=False
wildcard = r"Data files (*.dat)|*.dat|Text files (*.txt)|*.txt|ALL Files (*.*)|*.*"
open_dlg = wx.FileDialog(self,message='Choose a file',wildcard = wildcard, style=wx.OPEN|wx.CHANGE_DIR)
if open_dlg.ShowModal() == wx.ID_OK:
self.path=open_dlg.GetPath()
try:
self.MPL.ShowHelpString( self.path)
self.MPL.plotVideo111(self.path)
except IOError, error:
dlg = wx.MessageDialog(self, 'Error opening file\n' str(error))
dlg.ShowModal()
open_dlg.Destroy()
self.MPL.UpdatePlot()#必须刷新才能显示
def Button2Event(self,event):
self.MPL.flag1=True
self.MPL.flag2=False
self.MPL.flag3=False
try:
self.MPL.ShowVideo(self.path)
self.MPL.ShowHelpString(self.path)
except:
self.MPL.ShowHelpString(u"请先打开视频文件")
def Button3Event(self,event):
self.MPL.flag1=False
self.MPL.flag2=True
self.MPL.flag3=False
cv2.namedWindow('Capture person')
cv2.createTrackbar('Min','Capture person', self.MPL.MinScale, self.MPL.MaxScale, self.MPL.nothing)
try:
self.MPL.OpencvCaptureMovePerson(self.path)
self.MPL.ShowHelpString(self.path)
except:
self.MPL.ShowHelpString(u'请先打开图像')
def Button4Event(self,event):
self.MPL.Exit()
#自动创建状态栏
def StatusBar(self):
self.statusbar = self.CreateStatusBar()
self.statusbar.SetFieldsCount(3)
self.statusbar.SetStatusWidths([-2, -2, -1])
#About对话框
def AboutDialog(self):
dlg = wx.MessageDialog(self, '\twxMatPlotLib\t\nMPL_Panel_base,MPL_Panel,MPL_Frame and MPL2_Frame \n Created by Wu Xuping\n Version 1.0.0 \n 2012-02-01',
'About MPL_Frame and MPL_Panel', wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
###############################################################################
### MPL2_Frame添加了MPL_Panel的两个实例
###############################################################################
class MPL2_Frame(wx.Frame):
"""MPL2_Frame可以继承,并可修改,或者直接使用"""
def __init__(self,title="MPL2_Frame Example In wxPython",size=(850,500)):
wx.Frame.__init__(self,parent=None,title = title,size=size)
self.BoxSizer=wx.BoxSizer(wx.HORIZONTAL)
self.MPL1 = MPL_Panel_base(self)
self.BoxSizer.Add(self.MPL1,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND)
self.MPL2 = MPL_Panel_base(self)
self.BoxSizer.Add(self.MPL2,proportion =-1, border = 2,flag = wx.ALL | wx.EXPAND)
self.RightPanel = wx.Panel(self,-1)
self.BoxSizer.Add(self.RightPanel,proportion =0, border = 2,flag = wx.ALL | wx.EXPAND)
self.SetSizer(self.BoxSizer)
#创建FlexGridSizer
self.FlexGridSizer=wx.FlexGridSizer( rows=9, cols=1, vgap=5,hgap=5)
self.FlexGridSizer.SetFlexibleDirection(wx.BOTH)
#测试按钮1
self.Button1 = wx.Button(self.RightPanel,-1,"TestButton",size=(100,40),pos=(10,10))
self.Button1.Bind(wx.EVT_BUTTON,self.Button1Event)
#测试按钮2
self.Button2 = wx.Button(self.RightPanel,-1,"AboutButton",size=(100,40),pos=(10,10))
self.Button2.Bind(wx.EVT_BUTTON,self.Button2Event)
#加入Sizer中
self.FlexGridSizer.Add(self.Button1,proportion =0, border = 5,flag = wx.ALL | wx.EXPAND)
self.FlexGridSizer.Add(self.Button2,proportion =0, border = 5,flag = wx.ALL | wx.EXPAND)
self.RightPanel.SetSizer(self.FlexGridSizer)
#状态栏
self.StatusBar()
#MPL2_Frame界面居中显示
self.Centre(wx.BOTH)
#按钮事件,用于测试
def Button1Event(self,event):
self.MPL1.cla()#必须清理图形,才能显示下一幅图
x=np.arange(-5,5,0.2)
y=np.cos(x)
self.MPL1.plot(x,y,'--*g')
self.MPL1.xticker(2.0,1.0)
self.MPL1.yticker(0.5,0.1)
self.MPL1.title_MPL("MPL1")
self.MPL1.ShowHelpString("You Can Show MPL1 Helpful String Here !")
self.MPL1.grid()
self.MPL1.UpdatePlot()#必须刷新才能显示
self.MPL2.cla()
self.MPL2.plot(x,np.sin(x),':^b')
self.MPL2.xticker(1.0,0.5)
self.MPL2.yticker(0.2,0.1)
self.MPL2.title_MPL("MPL2")
self.MPL2.grid()
self.MPL2.UpdatePlot()
def Button2Event(self,event):
self.AboutDialog()
#自动创建状态栏
def StatusBar(self):
self.statusbar = self.CreateStatusBar()
self.statusbar.SetFieldsCount(3)
self.statusbar.SetStatusWidths([-2, -2, -1])
#About对话框
def AboutDialog(self):
dlg = wx.MessageDialog(self, '\twxMatPlotLib\t\nMPL_Panel_base,MPL_Panel,MPL_Frame and MPL2_Frame \n Created by Wu Xuping\n Version 1.0.0 \n 2012-02-01',
'About MPL_Frame and MPL_Panel', wx.OK | wx.ICON_INFORMATION)
dlg.ShowModal()
dlg.Destroy()
########################################################################
#主程序测试
if __name__ == '__main__':
app = wx.PySimpleApp()
#frame = MPL2_Frame()
frame =MPL_Frame()
frame.Center()
frame.Show()
frame.MPL.plotImage111(frame.path)
app.MainLoop()
标签:
相关软件
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明


网友评论
我要评论