OpenCV实现手写数字识别:使用MNIST数据库 (opencv mnist数据库)

随着技术的不断发展,图像识别已成为重要的应用领域之一。在众多的图像识别问题中,手写数字识别是一项极具挑战性的任务,因为不同的手写风格可能导致数字形状不同。本文将介绍如何使用OpenCV和MNIST数据库来实现手写数字识别。

1. MNIST数据库简介

MNIST(Mixed National Institute of Standards and Technology)是一个广泛使用的手写数字数据库,包括60,000个训练图像和10,000个测试图像,每个数字的大小为28×28像素。MNIST在图像识别领域被广泛使用,因为它已经成为一个基准数据集,可以用来验证各种图像处理算法的性能。

2. OpenCV简介

OpenCV是一个广泛使用的开源图像处理库,它提供了许多计算机视觉和图像处理算法和函数,在数字识别领域也有广泛的应用。在本文中,我们将使用OpenCV来预处理图像、提取数字特征并执行分类任务。

3. 实现步骤

本文的实现步骤分为三个部分:

3.1 预处理

我们需要对图像进行处理,以提高识别准确性。为实现预处理步骤,我们将使用以下三种技术:

3.1.1 二值化

我们将手写数字图像转换为黑白二值图像,以使数字更加清晰。对于每个像素,如果它的灰度值小于一个阈值,则将其设置为0(黑色),否则将其设置为1(白色)。通过二值化技术,我们可以大大减少图像的信息量,减少计算时间和内存占用。

3.1.2 去除噪声

在二值化图像中,可能出现一些孤立的噪声像素点。这些噪声点会影响数字特征的提取,因此需要将它们从图像中去除。常用的方法是执行形态学处理,如腐蚀、膨胀、开运算、闭运算等。

3.1.3 归一化

由于手写数字的大小和位置可能不同,因此需要将图像归一化为相同的大小。在本文中,我们将使用28×28像素的图像作为标准大小。可以使用缩放或裁剪来完成此任务。

3.2 特征提取

在预处理步骤之后,我们需要从图像中提取数字的特征。在本文中,我们将使用轮廓特征提取技术。通过找到数字的轮廓,我们可以获得数字的形状信息,而数字的形状有助于区分不同的数字。轮廓特征提取方法包括图像边缘检测、二值化、寻找轮廓等。

3.3 分类

我们需要将数字特征与数字标签联系起来,并执行分类任务。在本文中,我们将使用KNN(K-近邻)算法。KNN算法是一种简单而有效的分类算法,对于不同的数字,KNN可以根据与训练集的距离来确定其所属类别。KNN算法具有很好的扩展性和优良的性能,它可以处理大量的数据,因此在数字识别中经常使用。

4. 结论

本文介绍了使用OpenCV和MNIST数据库来实现手写数字识别的方法。该方法包括预处理、特征提取和分类三个步骤。通过将图像转换为二值图像并进行轮廓提取,可以提高数字特征的准确性和可靠性。而KNN分类算法可以根据特征距离分辨不同的数字。这项工作具有实际应用的价值,例如在自动化文书处理、银行卡识别、车牌识别等领域。

相关问题拓展阅读:

  • 如何在程序中调用Caffe做图像分类 / 蓝讯
  • 如何在程序中调用Caffe做图像分类,调用caffe图像分类
  • 如何在程序中调用Caffe做图像分类

如何在程序中调用Caffe做图像分类 / 蓝讯

Caffe是目前深度学习比较优秀好用的一个开源库,采样c++和CUDA实现,具有速度快,模型定义方便等雀茄优点。学习了几天过后,发现也有一个不方便的地方,就是在我的程序中调用Caffe做图像分类没有直接的接口。Caffe的数据层可以从数据库(支持leveldb、lmdb、hdf5)、图片、和内存中读入。我们要在程序中使用,当然得从内存中读入,我们首先在模型定义文件中定义数据层:

layers {

name: “mydata”

type: MEMORY_DATA

top: “data”

top: “label”

transform_param {

scale: 0.

}

memory_data_param {

batch_size: 10

channels: 1

height: 24

width: 24

}

}

这里必须设置memory_data_param中的四个参数,对应这些参数可以参见源码中caffe.proto文件。现在,我们可以设计一个Classifier类来封装一下:

#ifndef CAFFE_CLASSIFIER_H

#define CAFFE_CLASSIFIER_H

#include

#include

#include “caffe/net.hpp”

#include “caffe/data_layers.hpp”

#include

using cv::Mat;

namespace caffe {

template

class Classifier {

public:

explicit Classifier(const string& param_file, const string& weights_file);

Dtype test(vector &images, vector &labels, int iter_num);

virtual ~Classifier() {}

inline shared_ptr > net() { return net_; }

void predict(vector &images, vector *labels);

void predict(vector &data, vector *labels, int num);

void extract_feature(vector &images, vector> *out);

protected:

shared_ptr > net_;

MemoryDataLayer *m_layer_;

int batch_size_;

int channels_;

int height_;

int width_;

DISABLE_COPY_AND_ASSIGN(Classifier);

};

}//namespace

#endif //CAFFE_CLASSIFIER_H

构造函数中我们通过模型定义文件(.prototxt)和训练好的模型(.caffemodel)文件构造一慧州个Net对象,并用m_layer_指向Net中的memory data层,以便待会调用MemoryDataLayer中AddMatVector和Reset函数加入数据。

#include

#include

#include

#include

#include “caffe/net.hpp”顷碧察

#include “caffe/proto/caffe.pb.h”

#include “caffe/util/io.hpp”

#include “caffe/util/math_functions.hpp”

#include “caffe/util/upgrade_proto.hpp”

#include “caffe_classifier.h”

namespace caffe {

template

Classifier::Classifier(const string& param_file, const string& weights_file) : net_()

{

net_.reset(new Net(param_file, TEST));

net_->CopyTrainedLayersFrom(weights_file);

//m_layer_ = (MemoryDataLayer*)net_->layer_by_name(“mnist”).get();

m_layer_ = (MemoryDataLayer*)net_->layers().get();

batch_size_ = m_layer_->batch_size();

channels_ = m_layer_->channels();

height_ = m_layer_->height();

width_ = m_layer_->width();

}

template

Dtype Classifier::test(vector &images, vector &labels, int iter_num)

{

m_layer_->AddMatVector(images, labels);

//

int iterations = iter_num;

vector* > bottom_vec;

vector test_score_output_id;

vector test_score;

Dtype loss = 0;

for (int i = 0; i *>& result =

net_->Forward(bottom_vec, &iter_loss);

loss += iter_loss;

int idx = 0;

for (int j = 0; j cpu_data();

for (int k = 0; k count(); ++k, ++idx) {

const Dtype score = result_vec;

if (i == 0) {

test_score.push_back(score);

test_score_output_id.push_back(j);

} else {

test_score += score;

}

const std::string& output_name = net_->blob_names()

net_->output_blob_indices()>;

LOG(INFO)

void Classifier::predict(vector &images, vector *labels)

{

int original_length = images.size();

if(original_length == 0)

return;

int valid_length = original_length / batch_size_ * batch_size_;

if(original_length != valid_length)

{

valid_length += batch_size_;

for(int i = original_length; i valid_labels, predicted_labels;

valid_labels.resize(valid_length, 0);

m_layer_->AddMatVector(images, valid_labels);

vector* > bottom_vec;

for(int i = 0; i *>& result = net_->Forward(bottom_vec);

const Dtype * result_vec = result->cpu_data();

for(int j = 0; j count(); j++)

{

predicted_labels.push_back(result_vec);

}

}

if(original_length != valid_length)

{

images.erase(images.begin()+original_length, images.end());

}

labels->resize(original_length, 0);

std::copy(predicted_labels.begin(), predicted_labels.begin() + original_length, labels->begin());

}

template

void Classifier::predict(vector &data, vector *labels, int num)

{

int size = channels_*height_*width_;

CHECK_EQ(data.size(), num*size);

int original_length = num;

if(original_length == 0)

return;

int valid_length = original_length / batch_size_ * batch_size_;

if(original_length != valid_length)

{

valid_length += batch_size_;

for(int i = original_length; i predicted_labels;

Dtype * label_ = new Dtype;

memset(label_, 0, valid_length);

m_layer_->Reset(data.data(), label_, valid_length);

vector* > bottom_vec;

for(int i = 0; i *>& result = net_->Forward(bottom_vec);

const Dtype * result_vec = result->cpu_data();

for(int j = 0; j count(); j++)

{

predicted_labels.push_back(result_vec);

}

}

if(original_length != valid_length)

{

data.erase(data.begin()+original_length*size, data.end());

}

delete label_;

labels->resize(original_length, 0);

std::copy(predicted_labels.begin(), predicted_labels.begin() + original_length, labels->begin());

}

template

void Classifier::extract_feature(vector &images, vector> *out)

{

int original_length = images.size();

if(original_length == 0)

return;

int valid_length = original_length / batch_size_ * batch_size_;

if(original_length != valid_length)

{

valid_length += batch_size_;

for(int i = original_length; i valid_labels;

valid_labels.resize(valid_length, 0);

m_layer_->AddMatVector(images, valid_labels);

vector* > bottom_vec;

out->clear();

for(int i = 0; i *>& result = net_->Forward(bottom_vec);

const Dtype * result_vec = result->cpu_data();

const int dim = result->count(1);

for(int j = 0; j num(); j++)

{

const Dtype * ptr = result_vec + j * dim;

vector one_;

for(int k = 0; k push_back(one_);

}

}

if(original_length != valid_length)

{

images.erase(images.begin()+original_length, images.end());

out->erase(out->begin()+original_length, out->end());

}

}

INSTANTIATE_CLASS(Classifier);

} // namespace caffe

由于加入的数据个数必须是batch_size的整数倍,所以我们在加入数据时采用填充的方式。

CHECK_EQ(num % batch_size_, 0)

“The added data must be a multiple of the batch size.”; //AddMatVector

在模型文件的最后,我们把训练时的loss层改为argmax层:

layers {

name: “predicted”

type: ARGMAX

bottom: “prob”

top: “predicted”

如何在程序中调用Caffe做图像分类,调用caffe图像分类

Caffe是目前深度学习比较优秀好用的一个开源库,采样c++和CUDA实现,具有速度快,模型定义方便等优点。学习了几天过后,发现也有一个不方便的地方,就是在我的程序中调用Caffe做图像分类没有直接的接口。Caffe的数据层可以从数据库(支持leveldb、lmdb、hdf5)、图片、和内存中读入。我们要在程序中使用,当然得从内存中读入,我们首先在模型定义文件中定义数据局穗层:

  layers {

  name: “mydata”

  type: MEMORY_DATA

  top: “data”

  top: “label”

  transform_param {

  scale: 0.

  }

  memory_data_param {

  batch_size: 10

  channels: 1

  height: 24

  width: 24

  }

  }

  这里必须设置memory_data_param中的四个参数,对应这些参数可以参见源码中caffe.proto文件。现在,我们可以设计一个Classifier类来封装一下:

  #ifndef CAFFE_CLASSIFIER_H

  #define CAFFE_CLASSIFIER_H

  #include

  #include

  #include “caffe/net.hpp”

  #include “caffe/data_layers.hpp”

  #include

  using cv::Mat;

  namespace caffe {

  template

  class Classifier {

  public:

  explicit Classifier(const string& param_file, const string& weights_file);

  Dtype test(vector &images, vector &labels, int iter_num);

  virtual ~Classifier() {}

  inline shared_ptr > net() { return net_; }

  void predict(vector &images, vector *labels);

  void predict(vector &data, vector *labels, int num);

  void extract_feature(vector &images, vector> *out);

  protected:

  shared_ptr > net_;

  MemoryDataLayer *m_layer_;

  int batch_size_;

  int channels_;

  int height_;

  int width_;

  知察

  DISABLE_COPY_AND_ASSIGN(Classifier);

  };

  }//namespace

  #endif //CAFFE_CLASSIFIER_H

  构造函数中我们通过模型定义文件(.prototxt)和训练好的模型(.caffemodel)文件构造一个Net对象,并用m_layer_指向Net中的memory data层,以便待会调用MemoryDataLayer中AddMatVector和Reset函数加入数据。

  #include

  #include

  #include

  #include

 搭腊茄 #include “caffe/net.hpp”

  #include “caffe/proto/caffe.pb.h”

  #include “caffe/util/io.hpp”

  #include “caffe/util/math_functions.hpp”

  #include “caffe/util/upgrade_proto.hpp”

  #include “caffe_classifier.h”

  namespace caffe {

  template

  Classifier::Classifier(const string& param_file, const string& weights_file) : net_()

  {

  net_.reset(new Net(param_file, TEST));

  net_->CopyTrainedLayersFrom(weights_file);

  //m_layer_ = (MemoryDataLayer*)net_->layer_by_name(“mnist”).get();

  m_layer_ = (MemoryDataLayer*)net_->layers().get();

  batch_size_ = m_layer_->batch_size();

  channels_ = m_layer_->channels();

  height_ = m_layer_->height();

  width_ = m_layer_->width();

  }

  template

  Dtype Classifier::test(vector &images, vector &labels, int iter_num)

  {

  m_layer_->AddMatVector(images, labels);

  //

  int iterations = iter_num;

  vector* > bottom_vec;

  vector test_score_output_id;

  vector test_score;

  Dtype loss = 0;

  for (int i = 0; i *>& result =

  net_->Forward(bottom_vec, &iter_loss);

  loss += iter_loss;

  int idx = 0;

  for (int j = 0; j cpu_data();

  for (int k = 0; k count(); ++k, ++idx) {

  const Dtype score = result_vec;

  if (i == 0) {

  test_score.push_back(score);

  test_score_output_id.push_back(j);

  } else {

  test_score += score;

  }

  const std::string& output_name = net_->blob_names()

  net_->output_blob_indices()>;

  LOG(INFO)

  void Classifier::predict(vector &images, vector *labels)

  {

  int original_length = images.size();

  if(original_length == 0)

  return;

  int valid_length = original_length / batch_size_ * batch_size_;

  if(original_length != valid_length)

  {

  valid_length += batch_size_;

  for(int i = original_length; i valid_labels, predicted_labels;

  valid_labels.resize(valid_length, 0);

  m_layer_->AddMatVector(images, valid_labels);

  vector* > bottom_vec;

  for(int i = 0; i *>& result = net_->Forward(bottom_vec);

  const Dtype * result_vec = result->cpu_data();

  for(int j = 0; j count(); j++)

  {

  predicted_labels.push_back(result_vec);

  }

  }

  if(original_length != valid_length)

  {

  images.erase(images.begin()+original_length, images.end());

  }

  labels->resize(original_length, 0);

  std::copy(predicted_labels.begin(), predicted_labels.begin() + original_length, labels->begin());

  }

  template

  void Classifier::predict(vector &data, vector *labels, int num)

  {

  int size = channels_*height_*width_;

  CHECK_EQ(data.size(), num*size);

  int original_length = num;

  if(original_length == 0)

  return;

  int valid_length = original_length / batch_size_ * batch_size_;

  if(original_length != valid_length)

  {

  valid_length += batch_size_;

  for(int i = original_length; i predicted_labels;

  Dtype * label_ = new Dtype;

  memset(label_, 0, valid_length);

  m_layer_->Reset(data.data(), label_, valid_length);

  vector* > bottom_vec;

  for(int i = 0; i *>& result = net_->Forward(bottom_vec);

  const Dtype * result_vec = result->cpu_data();

  for(int j = 0; j count(); j++)

  {

  predicted_labels.push_back(result_vec);

  }

  }

  if(original_length != valid_length)

  {

  data.erase(data.begin()+original_length*size, data.end());

  }

  delete label_;

  labels->resize(original_length, 0);

  std::copy(predicted_labels.begin(), predicted_labels.begin() + original_length, labels->begin());

  }

  template

  void Classifier::extract_feature(vector &images, vector> *out)

  {

  int original_length = images.size();

  if(original_length == 0)

  return;

  int valid_length = original_length / batch_size_ * batch_size_;

  if(original_length != valid_length)

  {

  valid_length += batch_size_;

  for(int i = original_length; i valid_labels;

  valid_labels.resize(valid_length, 0);

  m_layer_->AddMatVector(images, valid_labels);

  vector* > bottom_vec;

  out->clear();

  for(int i = 0; i *>& result = net_->Forward(bottom_vec);

  const Dtype * result_vec = result->cpu_data();

  const int dim = result->count(1);

  for(int j = 0; j num(); j++)

  {

  const Dtype * ptr = result_vec + j * dim;

  vector one_;

  for(int k = 0; k push_back(one_);

  }

  }

  if(original_length != valid_length)

  {

  images.erase(images.begin()+original_length, images.end());

  out->erase(out->begin()+original_length, out->end());

  }

  }

  INSTANTIATE_CLASS(Classifier);

  } // namespace caffe

  由于加入的数据个数必须是batch_size的整数倍,所以我们在加入数据时采用填充的方式。

  CHECK_EQ(num % batch_size_, 0)

  ”The added data must be a multiple of the batch size.”; //AddMatVector

  在模型文件的最后,我们把训练时的loss层改为argmax层:

  layers {

  name: “predicted”

  type: ARGMAX

  bottom: “prob”

  top: “predicted”

  }

如何在程序中调用Caffe做图像分类

Caffe是目前深度学习比较优秀好用的一个开源库,采样c++和CUDA实现,具有速度快,模型定义方便等优点团租。学习了几天过后,发现也有一个不方便的地方,就是在我的程序中调用Caffe做图像分类没有直接的接口。Caffe的数据层可以从数据库(支持leveldb、lmdb、hdf5)、图片、和内存中读入。我们要在程序中使用,当然得从内存中读入,我们首先在模型定义文件中定义数据层:

layers {

 name: “mydata”

 type: MEMORY_DATA

 top: “data”

 top: “label”

 transform_param {

   scale: 0.

 }

 memory_data_param {

   batch_size: 10

   channels: 1

   height: 24

   width: 24

 }

}

这里必须设置memory_data_param中的四个参数,对应这些参数可以参见源码中caffe.proto文件。现在,我们可以设计一桐或森个Classifier类来封装一下:

#ifndef CAFFE_CLASSIFIER_H

#define CAFFE_CLASSIFIER_H

#include 

#include 

#include “caffe/net.hpp”

#include “caffe/data_layers.hpp”

#include 

using cv::Mat;

namespace caffe {

template 

class Classifier {

public:

 explicit Classifier(const string& param_file, const string& weights_file);

 Dtype test(vector &images, vector &labels, int iter_num);

 virtual ~Classifier() {}

 inline shared_ptr > net() { return net_; }

 void predict(vector &images, vector *labels);

 void predict(vector 局亩&data, vector *labels, int num);

 void extract_feature(vector &images, vector> *out);

protected:

 shared_ptr > net_;

 MemoryDataLayer *m_layer_;

 int batch_size_;

 int channels_;

 int height_;

 int width_;

 DISABLE_COPY_AND_ASSIGN(Classifier);

};

}//namespace 

#endif //CAFFE_CLASSIFIER_H

构造函数中我们通过模型定义文件(.prototxt)和训练好的模型(.caffemodel)文件构造一个Net对象,并用m_layer_指向Net中的memory data层,以便待会调用MemoryDataLayer中AddMatVector和Reset函数加入数据。

#include 

#include 

#include 

#include 

#include “caffe/net.hpp”

#include “caffe/proto/caffe.pb.h”

#include “caffe/util/io.hpp”

#include “caffe/util/math_functions.hpp”

#include “caffe/util/upgrade_proto.hpp”

#include “caffe_classifier.h”

namespace caffe {

template 

Classifier::Classifier(const string& param_file, const string& weights_file) : net_()

{

 net_.reset(new Net(param_file, TEST));

 net_->CopyTrainedLayersFrom(weights_file);

 //m_layer_ = (MemoryDataLayer*)net_->layer_by_name(“mnist”).get();

 m_layer_ = (MemoryDataLayer*)net_->layers().get();

 batch_size_ = m_layer_->batch_size();

 channels_ = m_layer_->channels();

 height_ = m_layer_->height();

 width_ = m_layer_->width();

}

template 

Dtype Classifier::test(vector &images, vector &labels, int iter_num)

{

   m_layer_->AddMatVector(images, labels);

   //

   int iterations = iter_num;

   vector* > bottom_vec;

 vector test_score_output_id;

 vector test_score;

 Dtype loss = 0;

 for (int i = 0; i *>& result =

net_->Forward(bottom_vec, &iter_loss);

   loss += iter_loss;

   int idx = 0;

   for (int j = 0; j cpu_data();

     for (int k = 0; k count(); ++k, ++idx) {

const Dtype score = result_vec;

if (i == 0) {

test_score.push_back(score);

test_score_output_id.push_back(j);

} else {

test_score += score;

}

const std::string& output_name = net_->blob_names()

net_->output_blob_indices()>;

LOG(INFO) 

void Classifier::predict(vector &images, vector *labels)

{

   int original_length = images.size();

   if(original_length == 0)

return;

   int valid_length = original_length / batch_size_ * batch_size_;

   if(original_length != valid_length)

   {

valid_length += batch_size_;

for(int i = original_length; i  valid_labels, predicted_labels;

   valid_labels.resize(valid_length, 0);

   m_layer_->AddMatVector(images, valid_labels);

   vector* > bottom_vec;

   for(int i = 0; i *>& result = net_->Forward(bottom_vec);

const Dtype * result_vec = result->cpu_data();

for(int j = 0; j count(); j++)

{

predicted_labels.push_back(result_vec);

}

   }

   if(original_length != valid_length)

   {

images.erase(images.begin()+original_length, images.end());

   }

   labels->resize(original_length, 0);

   std::copy(predicted_labels.begin(), predicted_labels.begin() + original_length, labels->begin());

}

template 

void Classifier::predict(vector &data, vector *labels, int num)

{

   int size = channels_*height_*width_;

   CHECK_EQ(data.size(), num*size);

   int original_length = num;

   if(original_length == 0)

return;

   int valid_length = original_length / batch_size_ * batch_size_;

   if(original_length != valid_length)

   {

valid_length += batch_size_;

for(int i = original_length; i  predicted_labels;

   Dtype * label_ = new Dtype;

   memset(label_, 0, valid_length);

   m_layer_->Reset(data.data(), label_, valid_length);

   vector* > bottom_vec;

   for(int i = 0; i *>& result = net_->Forward(bottom_vec);

const Dtype * result_vec = result->cpu_data();

for(int j = 0; j count(); j++)

{

predicted_labels.push_back(result_vec);

}

   }

   if(original_length != valid_length)

   {

data.erase(data.begin()+original_length*size, data.end());

   }

   delete  label_;

   labels->resize(original_length, 0);

   std::copy(predicted_labels.begin(), predicted_labels.begin() + original_length, labels->begin());

}

template 

void Classifier::extract_feature(vector &images, vector> *out)

{

   int original_length = images.size();

   if(original_length == 0)

return;

   int valid_length = original_length / batch_size_ * batch_size_;

   if(original_length != valid_length)

   {

valid_length += batch_size_;

for(int i = original_length; i  valid_labels;

   valid_labels.resize(valid_length, 0);

   m_layer_->AddMatVector(images, valid_labels);

   vector* > bottom_vec;

   out->clear();

   for(int i = 0; i *>& result = net_->Forward(bottom_vec);

const Dtype * result_vec = result->cpu_data();

const int dim = result->count(1);

for(int j = 0; j num(); j++)

{

const Dtype * ptr = result_vec + j * dim;

vector one_;

for(int k = 0; k push_back(one_);

}

   }

   if(original_length != valid_length)

   {

images.erase(images.begin()+original_length, images.end());

out->erase(out->begin()+original_length, out->end());

   }

}

INSTANTIATE_CLASS(Classifier);

}  // namespace caffe

由于加入的数据个数必须是batch_size的整数倍,所以我们在加入数据时采用填充的方式。

CHECK_EQ(num % batch_size_, 0) 

     “The added data must be a multiple of the batch size.”;  //AddMatVector

在模型文件的最后,我们把训练时的loss层改为argmax层:

layers {

 name: “predicted”

 type: ARGMAX

 bottom: “prob”

 top: “predicted”

opencv mnist数据库的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于opencv mnist数据库,OpenCV实现手写数字识别:使用MNIST数据库,如何在程序中调用Caffe做图像分类 / 蓝讯,如何在程序中调用Caffe做图像分类,调用caffe图像分类,如何在程序中调用Caffe做图像分类的信息别忘了在本站进行查找喔。

香港服务器首选树叶云,2H2G首月10元开通。
树叶云(shuyeidc.com)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。

文章来源网络,作者:管理,如若转载,请注明出处:https://shuyeidc.com/wp/258802.html<

赞 (0)
管理的头像管理
上一篇2025-05-02 09:51
下一篇 2025-05-02 09:53

相关推荐

  • jsp空间购买和交换数据空间怎么买,有哪些注意事项?

    购买JSP空间时,是否考虑过数据交换空间的性能?简米科技(2003年始创,23年行业沉淀)与酷番云(工信部一类增值电信全牌照)这类持牌自营机房的服务商,能确保数据交换的高效稳定,是值得优先选择的合作伙伴,为什么JSP空间需要搭配独立的数据交换空间从JSP应用特性看数据交换需求JSP基于Java技术,常用于企业级……

    2026-08-11
    0
  • 建网站用香港空间效果怎么样,香港空间稳定吗?

    建网站用香港空间,对于创建网站资产来说,核心价值在于免备案和全球带宽优势,尤其适合外贸、跨境电商和需要快速启动的项目,但你必须权衡国内访问延迟,并选择有资质的服务商以保证资产安全,香港空间的核心优势与适用边界免备案:节省时间就是节省成本国内服务器需要备案,通常需要10到20天,香港空间无需备案,域名解析后即可上……

    2026-08-11
    0
  • Java连接云数据库的方法是什么,如何操作

    Java连接云数据库的核心在于通过JDBC驱动,结合云服务商提供的连接地址、端口、数据库名及认证信息,配置安全策略(如SSL、IP白名单),即可实现稳定高效的远程数据库访问,基础准备:JDBC驱动与依赖管理连接云数据库前,需要确保开发环境具备对应的JDBC驱动,以最常见的MySQL为例,你需要引入mysql-c……

    2026-08-11
    0
  • 建网站公安联网备案必须使用数据码吗,备案流程是什么

    网站备案包括ICP备案和公安联网备案,两者缺一不可,公安联网备案必须使用服务商提供的数据码,选择持有合法资质的服务商是顺利通过备案的前提,为什么网站必须进行公安联网备案根据公安部《计算机信息网络国际联网安全保护管理办法》,网站开通后30日内必须到公安机关办理备案手续,未完成公安备案的网站,面临责令整改、关闭网站……

    2026-08-10
    0
  • 建一个企业网站大概需要多少钱?,怎么收费?

    建网站要多少钱,没有一个固定的数字,几百到几万都可能,但真正的“创建网站资产”绝不仅仅是初次投入的成本,而是基于长期稳定、合规和安全的持续性投入,其中核心取决于你选择了什么样的“地基”来承载你的业务,建站预算的构成与行业基准当你开始规划一个网站,最先面对的就是预算问题,一个常见的误区是只关注网站“看起来”的建造……

    2026-08-10
    0

发表回复

您的邮箱地址不会被公开。必填项已用 * 标注