想利用vtkBoxWidget和vtkExtractVOI实现剪裁。之前介绍过vtkBoxWidget,主要是说基本功能和接口,没有贴出完整实例。
  Study-VTK:vtkWidget 分割/配准类之 正交六面体3D小部件 vtkBoxWidget
  干脆直接介绍如何利用vtkwidget 实现剪裁。本文代码基本就是 cp 一遍vtk相关接口。


利用vtkwidget 实现剪裁

  • 1 利用vtkwidget 剪裁步骤
  • 2 利用vtkwidget 剪裁模型展示
  • 3 利用vtkwidget 剪裁模型代码
  • 4 利用vtkwidget 剪裁影像展示
  • 5 利用vtkwidget 剪裁影像代码

1 利用vtkwidget 剪裁步骤

实现剪裁需要三步:

  1. 输入被剪裁模型;
      被剪裁数据一般有:
        影像(vti/vtr格式 dcm/图片/矩阵 等数据)、
        模型(vtp/vtu格式 stl/obj/体网格 等数据)、
        场景

  2. 剪切区域选择(交互);
      vtk提供大量现成的交互vtkWidget。可以自己开发交互,我只搞过一个,很麻烦。现成的虽然丑点但是是很多前辈积累的,比较实用。一般不建议自己开发。跟剪切相关的,遵循kiss原则,大家直接想到的无非就是:
        平面上任意点两个点,模型分成两个部分
        平面上任意点多个点,练成闭合样条曲线,分成曲线内、曲线外
        空间放置一个球,分成球内求外
        空间放置一个立方体,截取立方体内外

  3. 剪切算法实现。
        模型的基本上是自己搞一个无限长的平面,利用在利用现成的与或非
        影像的话vtkExtractVOI可以实现任意剪裁

2 利用vtkwidget 剪裁模型展示

  临时搞一个demo,可以先看下效果。

  被剪裁模型:

  1. 本地stl文件

  剪切区域选择:

  1. 球、
  2. box、
  3. 平面任意两点、
  4. 平面任意多点

  剪切算法:

  1. vtkClipPolyData实现两个模型取并、
  2. vtkClipPolyData实现两个模型取异、
  3. vtkCutter实现两个模型去交线、
  4. vtkBoxClipDataSet生成无限平面后去并

stl、box、取交集

stl、box、取外部

stl、box、取交线

stl、ball、取交集

stl、ball、取外部

stl、平面直线、取最大连通域(直线设置比较细,录屏压缩后看不到了)

stl、平面多点、取最大连通域(顺时针内、逆时针外)

3 利用vtkwidget 剪裁模型代码

  vtkWidget 大部分使用方法基本一样,vtkBoxWidget举例

1 初始化

 if (widget_type_ == BOX) {if (clip_box_widget_ == nullptr) {clip_box_widget_ = vtkSmartPointer<vtkBoxWidget>::New();clip_box_widget_->GetFaceProperty()->SetColor(0.6, 0.6, 0.2);clip_box_widget_->GetFaceProperty()->SetOpacity(0.25);clip_box_widget_->SetInteractor(vmtk_renderer_->GetRenderWindowInteractor());}}

1 设置rans

  clip_box_widget_->GetTransform(transform_);

2 开启交互

    if (widget_type_ == BOX) {clip_box_widget_->SetInputData(surface_);clip_box_widget_->PlaceWidget();} else if (widget_type_ == SPHERE) {} else if (widget_type_ == LINE) {}if (transform_ && widget_type_ == BOX) {clip_box_widget_->SetTransform(transform_);clip_box_widget_->On();}

3 交互完成后获取数据

vtkSmartPointer<vtkClipPolyData> clipper = vtkSmartPointer<vtkClipPolyData>::New();vtkSmartPointer<vtkPlanes> clip_planes_function;vtkSmartPointer<vtkSphere> clip_sphere_function;clipper->SetInputData(surface_);clipper->GenerateClippedOutputOn();clipper->SetInsideOut(inside_out_);if (widget_type_ == BOX) {clip_planes_function = vtkSmartPointer<vtkPlanes>::New();clipper->SetClipFunction(clip_planes_function);} else if (widget_type_ == SPHERE) {clip_sphere_function = vtkSmartPointer<vtkSphere>::New();clipper->SetClipFunction(clip_sphere_function);}vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();cutter->SetInputData(surface_);if (widget_type_ == BOX) {cutter->SetCutFunction(clip_planes_function);} else if (widget_type_ == SPHERE) {cutter->SetCutFunction(clip_sphere_function);}clipped_surface_ = vtkSmartPointer<vtkPolyData>::New();cut_lines_ = vtkSmartPointer<vtkPolyData>::New();if (widget_type_ == BOX) {clip_box_widget_->GetPlanes(clip_planes_function);} else if (widget_type_ == SPHERE) {clip_sphere_widget_->GetSphere(clip_sphere_function);}clipper->Update();if (widget_type_ == BOX) {clip_box_widget_->Off();} else if (widget_type_ == SPHERE) {clip_sphere_widget_->Off();}cutter->Update();

4 关闭交互

    if (widget_type_ == BOX) {clip_box_widget_->Off();} else if (widget_type_ == SPHERE) {clip_sphere_widget_->Off();}



完整代码

  我这里把vtkSeedWidget、vtkBoxWidget、vtkSphereWidget封装在一起。

#ifndef VMTKSURFACECLIPPER_H
#define VMTKSURFACECLIPPER_H#include <QObject>
#include <QPointer>
#include "vmtkrenderer.h"#include <vtkPolyData.h>
#include <vtkTransform.h>
#include <vtkBoxWidget.h>
#include <vtkSeedWidget.h>
#include <vtkSmartPointer.h>
#include <vtkSphereWidget.h>class SurfaceClipper : public QObject {Q_OBJECTpublic:enum WidgetType {// 切割方式BOX,SPHERE,LINE};public:explicit SurfaceClipper(QObject *parent = nullptr);virtual ~SurfaceClipper() override;void Execute();void SetEnable(const bool value);void SetSurface(const vtkSmartPointer<vtkPolyData> value);void SetWidgetType(const WidgetType value);void SetTransform(const vtkSmartPointer<vtkTransform> value);void SetInsideOut(const bool value);void SetVmtkRenderer(const QPointer<VmtkRenderer> value);vtkSmartPointer<vtkPolyData> GetSurface() const;vtkSmartPointer<vtkPolyData> GetClippedSurface() const;vtkSmartPointer<vtkPolyData> GetCutLines() const;vtkSmartPointer<vtkTransform> GetTransForm() const;Q_SIGNALS:void SignalClippedFinish();private:void Initial();void Display();void ClipCallback();private Q_SLOTS:void SlotKeyPressed(const QString &key);void SlotSeedChanged(vtkObject *caller, unsigned long vtk_event,void *client_data, void *call_data);private:bool first_connect_;bool own_renderer_;bool inside_out_;QPointer<VmtkRenderer> vmtk_renderer_;vtkSmartPointer<vtkPolyData> surface_;vtkSmartPointer<vtkPolyData> clipped_surface_;vtkSmartPointer<vtkPolyData> cut_lines_;vtkSmartPointer<vtkEventQtSlotConnect> vtk_connections_;vtkSmartPointer<vtkSeedWidget> seed_widget_;vtkSmartPointer<vtkBoxWidget> clip_box_widget_;vtkSmartPointer<vtkSphereWidget> clip_sphere_widget_;vtkSmartPointer<vtkTransform> transform_;WidgetType widget_type_;
};#endif // VMTKSURFACECLIPPER_H
#include "vmtksurfaceclipper.h"
#include <QDebug>
#include <vtkPoints.h>
#include <vtkCamera.h>
#include <vtkCutter.h>
#include <vtkPlanes.h>
#include <vtkSphere.h>#include <vtkStripper.h>
#include <vtkProperty.h>
#include <vtkPointData.h>
#include <vtkProperty2D.h>
#include <vtkClipPolyData.h>
#include <vtkContourFilter.h>
#include <vtkCleanPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkBoxClipDataSet.h>
#include <vtkSeedRepresentation.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkPolyDataConnectivityFilter.h>
#include <vtkPointHandleRepresentation2D.h>SurfaceClipper::SurfaceClipper(QObject *parent) : QObject(parent) {Initial();
}SurfaceClipper::~SurfaceClipper() {if (own_renderer_) {vmtk_renderer_->deleteLater();}
}/*** @brief SurfaceClipper::Execute* ui交互开启*/
void SurfaceClipper::Execute() {qDebug();if (surface_ == nullptr) {qWarning() << "no Surface";return ;}if (vmtk_renderer_ == nullptr) {vmtk_renderer_ = new VmtkRenderer();vmtk_renderer_->Initialize();own_renderer_ = true;}if (widget_type_ == BOX) {if (clip_box_widget_ == nullptr) {clip_box_widget_ = vtkSmartPointer<vtkBoxWidget>::New();clip_box_widget_->GetFaceProperty()->SetColor(0.6, 0.6, 0.2);clip_box_widget_->GetFaceProperty()->SetOpacity(0.25);clip_box_widget_->SetInteractor(vmtk_renderer_->GetRenderWindowInteractor());}} else if (widget_type_ == SPHERE) {if (clip_sphere_widget_ == nullptr) {clip_sphere_widget_ = vtkSmartPointer<vtkSphereWidget>::New();clip_sphere_widget_->GetSphereProperty()->SetColor(0.6, 0.6, 0.2);clip_sphere_widget_->GetSphereProperty()->SetOpacity(0.25);clip_sphere_widget_->GetSelectedSphereProperty()->SetColor(0.6, 0.0, 0.0);clip_sphere_widget_->GetSelectedSphereProperty()->SetOpacity(0.75);clip_sphere_widget_->SetRepresentationToSurface();clip_sphere_widget_->SetPhiResolution(20);clip_sphere_widget_->SetThetaResolution(20);clip_sphere_widget_->SetInteractor(vmtk_renderer_->GetRenderWindowInteractor());}} else if (widget_type_ == LINE) {if (this->seed_widget_ == nullptr) {this->seed_widget_ = vtkSmartPointer<vtkSeedWidget>::New();vtkNew<vtkPointHandleRepresentation2D> handle_rep;handle_rep->GetProperty()->SetColor(1, 0, 0);vtkNew<vtkSeedRepresentation> widget_rep;widget_rep->SetHandleRepresentation(handle_rep);this->seed_widget_->SetInteractor(this->vmtk_renderer_->GetRenderWindowInteractor());this->seed_widget_->SetRepresentation(widget_rep);}qint32 num_seeds =this->seed_widget_->GetSeedRepresentation()->GetNumberOfSeeds();for (qint32 i = 0; i < num_seeds; ++i) {this->seed_widget_->GetSeedRepresentation()->RemoveLastHandle();this->seed_widget_->DeleteSeed(this->seed_widget_->GetSeedRepresentation()->GetNumberOfSeeds());}}if (first_connect_) {connect(vmtk_renderer_, &VmtkRenderer::SignalKeyPressed,this, &SurfaceClipper::SlotKeyPressed);this->vtk_connections_ = vtkSmartPointer<vtkEventQtSlotConnect>::New();vtk_connections_->Connect(seed_widget_, vtkCommand::PlacePointEvent,this, SLOT(SlotSeedChanged(vtkObject *, unsigned long,void *, void *)));first_connect_ = false;}transform_ = vtkSmartPointer<vtkTransform>::New();if (widget_type_ == BOX) {clip_box_widget_->GetTransform(transform_);}Display();if (own_renderer_) {vmtk_renderer_->Deallocate();}
}/*** @brief SurfaceClipper::SetSurface* 设置输入模型* @param value*/
void SurfaceClipper::SetSurface(const vtkSmartPointer<vtkPolyData> value) {surface_ = value;
}/*** @brief SurfaceClipper::SetWidgetType* 设置切割方式* @param value*/
void SurfaceClipper::SetWidgetType(const SurfaceClipper::WidgetType value) {widget_type_ = value;
}/*** @brief SurfaceClipper::SetTransform* 设置Trans转换* @param value*/
void SurfaceClipper::SetTransform(const vtkSmartPointer<vtkTransform> value) {transform_ = value;
}/*** @brief SurfaceClipper::SetInsideOut* 设置是否取反* @param value*/
void SurfaceClipper::SetInsideOut(const bool value) {inside_out_ = value;
}/*** @brief SurfaceClipper::SetVmtkRenderer* 输入Renderer* @param value*/
void SurfaceClipper::SetVmtkRenderer(const QPointer<VmtkRenderer> value) {vmtk_renderer_ = value;
}/*** @brief SurfaceClipper::GetSurface* 获取剪切后模型(交)* @return*/
vtkSmartPointer<vtkPolyData> SurfaceClipper::GetSurface() const {return surface_;
}/*** @brief SurfaceClipper::GetClippedSurface* 获取剪切后模型(异)* @return*/
vtkSmartPointer<vtkPolyData> SurfaceClipper::GetClippedSurface() const {return clipped_surface_;
}/*** @brief SurfaceClipper::GetCutLines* 获取剪切后交线* @return*/
vtkSmartPointer<vtkPolyData> SurfaceClipper::GetCutLines() const {return cut_lines_;
}/*** @brief SurfaceClipper::GetTransForm* BOX模式剪切转换* @return*/
vtkSmartPointer<vtkTransform> SurfaceClipper::GetTransForm() const {return transform_;
}/*** @brief SurfaceClipper::Initial* 初始化*/
void SurfaceClipper::Initial() {surface_ = nullptr;clipped_surface_ = nullptr;cut_lines_ = nullptr;vmtk_renderer_ = nullptr;clip_box_widget_ = nullptr;clip_sphere_widget_ = nullptr;first_connect_ = true;own_renderer_ = false;transform_ = nullptr;widget_type_ = LINE;inside_out_ = true;setObjectName("vmtksurfaceclipper");
}/*** @brief SurfaceClipper::Display* 开启widget*/
void SurfaceClipper::Display() {if (widget_type_ == BOX) {clip_box_widget_->SetInputData(surface_);clip_box_widget_->PlaceWidget();} else if (widget_type_ == SPHERE) {clip_sphere_widget_->SetInputData(surface_);clip_sphere_widget_->PlaceWidget();clip_sphere_widget_->On();} else if (widget_type_ == LINE) {this->seed_widget_->On();}if (transform_ && widget_type_ == BOX) {clip_box_widget_->SetTransform(transform_);clip_box_widget_->On();}vmtk_renderer_->Render();
}/*** @brief SurfaceClipper::ClipCallback* 剪裁函数*/
void SurfaceClipper::ClipCallback() {qDebug();if ((widget_type_ == BOX &&clip_box_widget_->GetEnabled() != 1) ||(widget_type_ == SPHERE &&clip_sphere_widget_->GetEnabled() != 1)) {return ;}if(widget_type_ == LINE) {if (this->seed_widget_->GetSeedRepresentation()->GetNumberOfSeeds() != 2|| this->surface_ == nullptr) {return ;}double pos1[3], pos2[3];this->seed_widget_->GetSeedRepresentation()->GetSeedWorldPosition(0, pos1);this->seed_widget_->GetSeedRepresentation()->GetSeedWorldPosition(1, pos2);this->seed_widget_->Off();QList<QList<double>> pts = {{0, 0, 0},{1, 0, 0},{1, 1, 0},{0, 1, 0},{0, 0, 1},{1, 0, 1},{1, 1, 1},{0, 1, 1}};vtkNew<vtkPoints> points;for (qint32 i = 0; i < pts.size(); ++i) {points->InsertPoint(i, pts[i][0], pts[i][1], pts[i][2]);}double direction[3];this->vmtk_renderer_->GetRenderer()->GetActiveCamera()->GetDirectionOfProjection(direction);points->SetPoint(0,pos1[0] - direction[0] * 1000,pos1[1] - direction[1] * 1000,pos1[2] - direction[2] * 1000);points->SetPoint(3,pos1[0] + direction[0] * 1000,pos1[1] + direction[1] * 1000,pos1[2] + direction[2] * 1000);points->SetPoint(1,pos2[0] - direction[0] * 1000,pos2[1] - direction[1] * 1000,pos2[2] - direction[2] * 1000);points->SetPoint(2,pos2[0] + direction[0] * 1000,pos2[1] + direction[1] * 1000,pos2[2] + direction[2] * 1000);double direction2[3], direction_offset[3];direction2[0] = pos1[0] - pos2[0];direction2[1] = pos1[1] - pos2[1];direction2[2] = pos1[2] - pos2[2];vtkMath::Cross(direction, direction2, direction_offset);points->SetPoint(4,pos1[0] - direction[0] * 1000 + direction_offset[0] * 0.01,pos1[1] - direction[1] * 1000 + direction_offset[1] * 0.01,pos1[2] - direction[2] * 1000 + direction_offset[2] * 0.01);points->SetPoint(7,pos1[0] + direction[0] * 1000 + direction_offset[0] * 0.01,pos1[1] + direction[1] * 1000 + direction_offset[1] * 0.01,pos1[2] + direction[2] * 1000 + direction_offset[2] * 0.01);points->SetPoint(5,pos2[0] - direction[0] * 1000 + direction_offset[0] * 0.01,pos2[1] - direction[1] * 1000 + direction_offset[1] * 0.01,pos2[2] - direction[2] * 1000 + direction_offset[2] * 0.01);points->SetPoint(6,pos2[0] + direction[0] * 1000 + direction_offset[0] * 0.01,pos2[1] + direction[1] * 1000 + direction_offset[1] * 0.01,pos2[2] + direction[2] * 1000 + direction_offset[2] * 0.01);vtkNew<vtkBoxClipDataSet> box_clip;box_clip->SetInputData(this->surface_);box_clip->GenerateClippedOutputOn();double n0[3], n1[3], n2[3], n3[3], n4[3], n5[3];double p0[3], p1[3], p2[3], p3[3], p4[3], p5[3];double pt0[3], pt1[3], pt2[3], pt3[3], pt4[3], pt5[3], pt6[3], pt7[3];points->GetPoint(0, pt0);points->GetPoint(1, pt1);points->GetPoint(2, pt2);points->GetPoint(3, pt3);points->GetPoint(4, pt4);points->GetPoint(5, pt5);points->GetPoint(6, pt6);points->GetPoint(7, pt7);for (qint32 i = 0; i < 3; ++i) {p0[i] = (pt1[i] + pt3[i]) / 2;n0[i] = (pt1[i] - pt5[i]);p1[i] = (pt5[i] + pt7[i]) / 2;n1[i] = (pt5[i] - pt1[i]);p2[i] = (pt2[i] + pt5[i]) / 2;n2[i] = (pt5[i] - pt4[i]);p3[i] = (pt3[i] + pt4[i]) / 2;n3[i] = (pt4[i] - pt5[i]);p4[i] = (pt0[i] + pt5[i]) / 2;n4[i] = (pt5[i] - pt6[i]);p5[i] = (pt2[i] + pt7[i]) / 2;n5[i] = (pt6[i] - pt5[i]);}box_clip->SetBoxClip(n0, p0,n1, p1,n2, p2,n3, p3,n4, p4,n5, p5);vtkNew<vtkDataSetSurfaceFilter> surface_in;surface_in->SetInputConnection(box_clip->GetOutputPort(0));vtkNew<vtkDataSetSurfaceFilter> surface_out;surface_out->SetInputConnection(box_clip->GetOutputPort(1));vtkNew<vtkPolyDataConnectivityFilter> connectivity_filter;connectivity_filter->SetInputConnection(surface_out->GetOutputPort());connectivity_filter->SetExtractionModeToLargestRegion();connectivity_filter->Update();this->surface_ = connectivity_filter->GetOutput();return;}vtkSmartPointer<vtkClipPolyData> clipper = vtkSmartPointer<vtkClipPolyData>::New();vtkSmartPointer<vtkPlanes> clip_planes_function;vtkSmartPointer<vtkSphere> clip_sphere_function;clipper->SetInputData(surface_);clipper->GenerateClippedOutputOn();clipper->SetInsideOut(inside_out_);if (widget_type_ == BOX) {clip_planes_function = vtkSmartPointer<vtkPlanes>::New();clipper->SetClipFunction(clip_planes_function);} else if (widget_type_ == SPHERE) {clip_sphere_function = vtkSmartPointer<vtkSphere>::New();clipper->SetClipFunction(clip_sphere_function);}vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();cutter->SetInputData(surface_);if (widget_type_ == BOX) {cutter->SetCutFunction(clip_planes_function);} else if (widget_type_ == SPHERE) {cutter->SetCutFunction(clip_sphere_function);}clipped_surface_ = vtkSmartPointer<vtkPolyData>::New();cut_lines_ = vtkSmartPointer<vtkPolyData>::New();if (widget_type_ == BOX) {clip_box_widget_->GetPlanes(clip_planes_function);} else if (widget_type_ == SPHERE) {clip_sphere_widget_->GetSphere(clip_sphere_function);}clipper->Update();if (widget_type_ == BOX) {clip_box_widget_->Off();} else if (widget_type_ == SPHERE) {clip_sphere_widget_->Off();}cutter->Update();cut_lines_->DeepCopy(cutter->GetOutput());surface_->DeepCopy(clipper->GetOutput());clipped_surface_->DeepCopy(clipper->GetClippedOutput());
}/*** @brief SurfaceClipper::SlotKeyPressed* 键盘回调函数* @param key*/
void SurfaceClipper::SlotKeyPressed(const QString &key) {if (key == "space") {ClipCallback();emit SignalClippedFinish();} else if (key == "Escape") {if (widget_type_ == BOX) {clip_box_widget_->Off();} else if (widget_type_ == SPHERE) {clip_sphere_widget_->Off();} else if (widget_type_ == SPHERE) {seed_widget_->Off();}emit SignalClippedFinish();}
}/*** @brief SurfaceClipper::SetEnable* 设置是否启动* @param value*/
void SurfaceClipper::SetEnable(const bool value) {if (widget_type_ == BOX) {clip_box_widget_->SetEnabled(value);} else if (widget_type_ == SPHERE) {clip_sphere_widget_->SetEnabled(value);}
}/*** @brief SurfaceClipper::SlotSeedChanged* 点选取后槽函数* @param caller* @param vtk_event* @param client_data* @param call_data*/
void SurfaceClipper::SlotSeedChanged(vtkObject *caller, unsigned long vtk_event,void *client_data, void *call_data) {Q_UNUSED(client_data)if (vtk_event == vtkCommand::PlacePointEvent) {qint32 n = *static_cast<int *>(call_data);vtkSmartPointer<vtkSeedWidget> widget = dynamic_cast<vtkSeedWidget *>(caller);if (n >= 0 && widget) {qint32 num_seeds = widget->GetSeedRepresentation()->GetNumberOfSeeds();if (num_seeds > 2) {this->seed_widget_->DeleteSeed(0);}}}
}

4 利用vtkwidget 剪裁影像展示

  影像剪裁一般在平面选择切割方向让后利用vtkExtractVOI重新切割影像,网友问vtkExtractVOI + vtkBoxWidget应该是在空间剪裁。方法跟上边模型切割一样,周末不上边了补上。

5 利用vtkwidget 剪裁影像代码

Study-VTK:三维影像实现任意方向、大小的切割

利用vtkwidget 实现剪裁相关推荐

  1. vtk 剪切 剪裁 切割 手动画任意曲面切割三维模型 汇总

    接触 VTK 有一段时间,数据剪切用的相对比较多,这里做一个汇总: vtkPlaneWidget 剪切,平面,体 vtkPlaneWidget 剪切,平面,体_恋恋西风的博客-CSDN博客 vtk 使 ...

  2. c语言剪裁矩形,六、矩形、区域和剪裁—CLOVER程序

    CLOVER程序用四个椭圆组成一个剪裁区域,将这个剪裁区域选进设备内容中,然后画出从窗口显示区域的中心出发的一系列直线,这些直线只出现在剪裁区域所限定的范围,结果显示如图5-20所示. 要用常规的方法 ...

  3. windows 8 .1全家桶(很详细)

    系统特性 开始屏幕 Windows 8.1恢复了"开始"按钮,但该按钮是欺骗性质的,点击后是打开的是开始屏幕(Modern UI):在Windows 8.1 Update在此界面右 ...

  4. 第05章 图形基础

    图形设备接口(GDI:Graphics Device Interface)是Windows的子系统,它负责在视讯显示器和打印机上显示图形.正如您所认为的那样,GDI是Windows非常重要的部分.不只 ...

  5. 图案设计灵感怎么写_设计的灵感来源

    一.设计的灵感来源 本系列的灵感来源于林华的 <黑白画> , 我脑海中就有闪过黑白画这一应用几乎和人类 文明同样的古老, 我们现今发现的古代遗址中大量的装饰品. 陶器等就有许多堪称 &qu ...

  6. Alphapose论文代码详解

    注:B站有相应视频,点击此链接即可跳转观看https://www.bilibili.com/video/BV1hb4y117mu/ 第1节 人体姿态估计的基本概念 第2节:Alphapose 2.1A ...

  7. 柯罗芭KLOVA打造东方女性专属服装 尽显女性柔和魅力

    近年来女性服装支出逐年增加,其中女性服装中轻奢价位的设计师品牌获得了最快发展.国产女装品牌柯罗芭KLOVA凭借其服装优良的品质.更适合亚洲女性身材的剪裁以及柔和素雅的色调等特点受到广泛好评. 以柯罗芭 ...

  8. vue导入音乐_比VUE更强大、更易上手的视频剪辑App,小白也能轻松出大片

    对于经常使用手机剪辑视频的用户来说,InShot一定不陌生.凭借功能强大.操作简单的优势,InShot一直备受推崇. 而其发行商InShot Inc.的实力远不止如此.这家成立于2011年的手机应用开 ...

  9. web前端入门到实战:实现CSS形状变换

    CSS3的"clip-path",这个"clip-path"看起来有点眼熟,因为它原本就存在于SVG里头,利用掩码(剪裁)的方法,连接坐标绘制掩码区域,就可以做 ...

最新文章

  1. POJ 1057 File Mapping 最详细的解题报告
  2. mysql引擎测试_MySQL MyISAM引擎和InnoDB引擎的性能测试
  3. CNN经典模型:GoogLeNet(从Inception v1到v4的演进)
  4. 关于Hystrix的几个问题
  5. 【英语学习】【WOTD】leviathan 释义/词源/示例
  6. 果然十三香!iPhone13系列正式发布:看到价格后酸了
  7. SAP License:SAP Netweaver
  8. JS实现 EventBus
  9. javascript之奇淫技巧
  10. 浅谈vue 动态加载、注册组件
  11. 「好文分享」我为什么从Google 辞职开始为自己工作?
  12. 使用Android Studio开发widget安卓桌面插件
  13. 3D目标检测基础知识
  14. 汇编之EBP的认识。
  15. intellij idea 工具栏的隐藏和显示
  16. C++课程设计——电话簿(文件流)
  17. GNU/Linux与Windows魔兽争霸3局域网对战安装与配置
  18. 同学用javascript写好了论坛自动灌水机。
  19. 2011年3月份优秀PPT资源分享
  20. import、from import及import as详解

热门文章

  1. android app 退出功能,Android 应用技巧: 手把手教你 优雅实现 “一键退出 App”
  2. 蓝桥杯模板TemplatePart12:NE555定时器频率测量
  3. git查看打tag时间_git打tag
  4. ChatGPT可以作为一个翻译器吗?
  5. Java POI 导出EXCEL经典实现 Java导出Excel弹出下载框
  6. 获取全国省地市地图json数据
  7. 一步步搞定Android行情K线蜡烛图(带十字光标)
  8. 小白谈谈singleton那些事儿
  9. 7、最小生成树,克鲁斯卡尔(Kruskal)算法
  10. 计算机科学技术的道与术