毕设分享 深度学习昆虫识别系统(源码+论文)
文章目录0 前言1 项目运行效果2 设计原理3 数据收集和处理4 卷积神经网络4.1卷积层4.2 池化层4.3 激活函数4.4 全连接层4.5 使用tensorflow中keras模块实现卷积神经网络5 MobileNetV2网络6 损失函数softmax 交叉熵6.1 softmax函数6.2 交叉熵损失函数7 优化器SGD8 学习率衰减策略9 最后0 前言这两年开始毕业设计和毕业答辩的要求和难度不断提升传统的毕设题目缺少创新和亮点往往达不到毕业答辩的要求这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。并且很难找到完整的毕设参考学习资料。为了大家能够顺利以及最少的精力通过毕设学长分享优质毕业设计项目提供大家参考学习今天要分享的是毕业设计 深度学习昆虫识别系统源码论文学长这里给一个题目综合评分(每项满分5分)难度系数3分工作量3分创新点4分项目分享见主页任意置顶文章1 项目运行效果视频效果毕业设计 深度学习昆虫识别系统2 设计原理以一个demo作为样例讲解大致原理实际工程要更为细致复杂。中国是农业大国在传统的农业生产中经常会受到病虫害问题的困扰。在解决病虫害问题时第一步是识别昆虫。在传统的昆虫识别方法中昆虫专家根据专业知识观察昆虫的外部特征并对照相关的昆虫图鉴进行识别费时费力。如今传统的昆虫识别方法逐渐被昆虫图像识别技术代替。目前常用的昆虫识别技术有图像识别法、微波雷达检测法、生物光子检测法、取样检测法、近红外及高光谱法、声测法等。近年来随着人工智能的迅速发展深度学习技术在处理自然语言、机器视觉等方面取得了很多成果随着深度学习的发展已经有研究人员开始将深度学习技术应用于昆虫的图像识别。文章旨在利用基于深度学习的图像识别技术解决昆虫识别问题希望能给现实生活中的病虫害识别问题提供新的解决问题的思路。3 数据收集和处理数据是深度学习的基石数据的主要来源有: 百度图片, 必应图片, 新浪微博, 百度贴吧, 新浪博客和一些专业的昆虫网站等爬虫爬取的图像的质量参差不齐, 标签可能有误, 且存在重复文件, 因此必须清洗。清洗方法包括自动化清洗, 半自动化清洗和手工清洗。自动化清洗包括:滤除小尺寸图像.滤除宽高比很大或很小的图像.滤除灰度图像.图像去重: 根据图像感知哈希.半自动化清洗包括:图像级别的清洗: 利用预先训练的昆虫/非昆虫图像分类器对图像文件进行打分, 非昆虫图像应该有较低的得分; 利用前一阶段的昆虫分类器对图像文件 (每个文件都有一个预标类别) 进行预测, 取预标类别的概率值为得分, 不属于原预标类别的图像应该有较低的得分. 可以设置阈值, 滤除很低得分的文件; 另外利用得分对图像文件进行重命名, 并在资源管理器选择按文件名排序, 以便于后续手工清洗掉非昆虫图像和不是预标类别的图像.类级别的清洗手工清洗: 人工判断文件夹下图像是否属于文件夹名所标称的物种, 这需要相关的昆虫学专业知识, 是最耗时且枯燥的环节。4 卷积神经网络卷积神经网络Convolutional Neural NetwoekCNN是一种前馈神经网络它的人工神经元可以局部响应周围的神经元每个神经元都接收一些输入并做一些点积计算。它通常包含卷积层、激活层、池化层、全连接层。4.1卷积层卷积核相当于一个滑动窗口示意图中x大小的卷积核依次划过x大小的输入数据中的对应区域并与卷积核滑过区域做矩阵点乘将所得结果依次填入对应位置即可得到右侧x尺寸的卷积特征图例如划到右上角x所圈区域时将进行xxxxxxxxxx的计算操作并将得到的数值填充到卷积特征的右上角。4.2 池化层池化操作又称为降采样提取网络主要特征可以在达到空间不变性的效果同时有效地减少网络参数因而简化网络计算复杂度防止过拟合现象的出现。在实际操作中经常使用最大池化或平均池化两种方式如下图所示。虽然池化操作可以有效的降低参数数量但过度池化也会导致一些图片细节的丢失因此在搭建网络时要根据实际情况来调整池化操作。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UTsB7AhE-1658995487680)4.3 激活函数激活函数大致分为两种在卷积神经网络的发展前期使用较为传统的饱和激活函数主要包括sigmoid函数、tanh函数等随着神经网络的发展研宄者们发现了饱和激活函数的弱点并针对其存在的潜在问题研宄了非饱和激活函数其主要含有ReLU函数及其函数变体4.4 全连接层在整个网络结构中起到“分类器”的作用经过前面卷积层、池化层、激活函数层之后网络己经对输入图片的原始数据进行特征提取并将其映射到隐藏特征空间全连接层将负责将学习到的特征从隐藏特征空间映射到样本标记空间一般包括提取到的特征在图片上的位置信息以及特征所属类别概率等。将隐藏特征空间的信息具象化也是图像处理当中的重要一环。4.5 使用tensorflow中keras模块实现卷积神经网络classCNN(tf.keras.Model):def__init__(self):super().__init__()self.conv1tf.keras.layers.Conv2D(filters32,# 卷积层神经元卷积核数目kernel_size[5,5],# 感受野大小paddingsame,# padding策略vaild 或 sameactivationtf.nn.relu# 激活函数)self.pool1tf.keras.layers.MaxPool2D(pool_size[2,2],strides2)self.conv2tf.keras.layers.Conv2D(filters64,kernel_size[5,5],paddingsame,activationtf.nn.relu)self.pool2tf.keras.layers.MaxPool2D(pool_size[2,2],strides2)self.flattentf.keras.layers.Reshape(target_shape(7*7*64,))self.dense1tf.keras.layers.Dense(units1024,activationtf.nn.relu)self.dense2tf.keras.layers.Dense(units10)defcall(self,inputs):xself.conv1(inputs)# [batch_size, 28, 28, 32]xself.pool1(x)# [batch_size, 14, 14, 32]xself.conv2(x)# [batch_size, 14, 14, 64]xself.pool2(x)# [batch_size, 7, 7, 64]xself.flatten(x)# [batch_size, 7 * 7 * 64]xself.dense1(x)# [batch_size, 1024]xself.dense2(x)# [batch_size, 10]outputtf.nn.softmax(x)returnoutput5 MobileNetV2网络简介MobileNet网络是Google最近提出的一种小巧而高效的CNN模型其在accuracy和latency之间做了折中。主要改进点相对于MobileNetV1MobileNetV2 主要改进点引入倒残差结构先升维再降维增强梯度的传播显著减少推理期间所需的内存占用Inverted Residuals去掉 Narrow layer(low dimension or depth) 后的 ReLU保留特征多样性增强网络的表达能力Linear Bottlenecks网络为全卷积使得模型可以适应不同尺寸的图像使用 RELU6最高输出为 6激活函数使得模型在低精度计算下具有更强的鲁棒性MobileNetV2 Inverted residual block 如下所示若需要下采样可在 DW 时采用步长为 2 的卷积小网络使用小的扩张系数expansion factor大网络使用大一点的扩张系数expansion factor推荐是5~10论文中 t 6 t 6t6倒残差结构Inverted residual blockResNet的Bottleneck结构是降维-卷积-升维是两边细中间粗而MobileNetV2是先升维6倍- 卷积 - 降维是沙漏形。区别于MobileNetV1, MobileNetV2的卷积结构如下因为DW卷积不改变通道数所以如果上一层的通道数很低时DW只能在低维空间提取特征效果不好。所以V2版本在DW前面加了一层PW用来升维。同时V2去除了第二个PW的激活函数改用线性激活因为激活函数在高维空间能够有效地增加非线性但在低维空间时会破坏特征。由于第二个PW主要的功能是降维所以不宜再加ReLU6。tensorflow相关实现代码importtensorflowastfimportnumpyasnpfromtensorflow.kerasimportlayers,Sequential,ModelclassConvBNReLU(layers.Layer):def__init__(self,out_channel,kernel_size3,strides1,**kwargs):super(ConvBNReLU,self).__init__(**kwargs)self.convlayers.Conv2D(filtersout_channel,kernel_sizekernel_size,stridesstrides,paddingSAME,use_biasFalse,nameConv2d)self.bnlayers.BatchNormalization(momentum0.9,epsilon1e-5,nameBatchNorm)self.activationlayers.ReLU(max_value6.0)# ReLU6defcall(self,inputs,trainingFalse,**kargs):xself.conv(inputs)xself.bn(x,trainingtraining)xself.activation(x)returnxclassInvertedResidualBlock(layers.Layer):def__init__(self,in_channel,out_channel,strides,expand_ratio,**kwargs):super(InvertedResidualBlock,self).__init__(**kwargs)self.hidden_channelin_channel*expand_ratio self.use_shortcut(strides1)and(in_channelout_channel)layer_list[]# first bottleneck does not need 1*1 convifexpand_ratio!1:# 1x1 pointwise convlayer_list.append(ConvBNReLU(out_channelself.hidden_channel,kernel_size1,nameexpand))layer_list.extend([# 3x3 depthwise convlayers.DepthwiseConv2D(kernel_size3,paddingSAME,stridesstrides,use_biasFalse,namedepthwise),layers.BatchNormalization(momentum0.9,epsilon1e-5,namedepthwise/BatchNorm),layers.ReLU(max_value6.0),#1x1 pointwise conv(linear)# linear activation y x - no activation functionlayers.Conv2D(filtersout_channel,kernel_size1,strides1,paddingSAME,use_biasFalse,nameproject),layers.BatchNormalization(momentum0.9,epsilon1e-5,nameproject/BatchNorm)])self.main_branchSequential(layer_list,nameexpanded_conv)defcall(self,inputs,**kargs):ifself.use_shortcut:returninputsself.main_branch(inputs)else:returnself.main_branch(inputs)6 损失函数softmax 交叉熵6.1 softmax函数Softmax函数由下列公式定义softmax 的作用是把 一个序列变成概率。softmax用于多分类过程中它将多个神经元的输出映射到0,1区间内所有概率的和将等于1。python实现defsoftmax(x):shift_xx-np.max(x)# 防止输入增大时输出为nanexp_xnp.exp(shift_x)returnexp_x/np.sum(exp_x)PyTorch封装的Softmax()函数dim参数dim为0时对所有数据进行softmax计算dim为1时对某一个维度的列进行softmax计算dim为-1 或者2 时对某一个维度的行进行softmax计算importtorch xtorch.tensor([2.0,1.0,0.1])x.cuda()outputstorch.softmax(x,dim0)print(输入,x)print(输出,outputs)print(输出之和,outputs.sum())6.2 交叉熵损失函数定义如下:python实现defcross_entropy(a,y):returnnp.sum(np.nan_to_num(-y*np.log(a)-(1-y)*np.log(1-a)))# tensorflow versionlosstf.reduce_mean(-tf.reduce_sum(y_*tf.log(y),reduction_indices[1]))# numpy versionlossnp.mean(-np.sum(y_*np.log(y),axis1))PyTorch实现交叉熵函数分为二分类(torch.nn.BCELoss())和多分类函数(torch.nn.CrossEntropyLoss()# 二分类 损失函数losstorch.nn.BCELoss()lloss(predreal)# 多分类损失函数losstorch.nn.CrossEntropyLoss()7 优化器SGD简介SGD全称Stochastic Gradient Descent随机梯度下降1847年提出。每次选择一个mini-batch而不是全部样本使用梯度下降来更新模型参数。它解决了随机小批量样本的问题但仍然有自适应学习率、容易卡在梯度较小点等问题。pytorch调用方法torch.optim.SGD(params,lrrequired parameter,momentum0,dampening0,weight_decay0,nesterovFalse)相关代码defstep(self,closureNone):Performs a single optimization step. Arguments: closure (callable, optional): A closure that reevaluates the model and returns the loss. lossNoneifclosureisnotNone:lossclosure()forgroupinself.param_groups:weight_decaygroup[weight_decay]# 权重衰减系数momentumgroup[momentum]# 动量因子0.9或0.8dampeninggroup[dampening]# 梯度抑制因子nesterovgroup[nesterov]# 是否使用nesterov动量forpingroup[params]:ifp.gradisNone:continued_pp.grad.dataifweight_decay!0:# 进行正则化# add_表示原处改变d_p d_p weight_decay*p.datad_p.add_(weight_decay,p.data)ifmomentum!0:param_stateself.state[p]# 之前的累计的数据v(t-1)# 进行动量累计计算ifmomentum_buffernotinparam_state:bufparam_state[momentum_buffer]torch.clone(d_p).detach()else:# 之前的动量bufparam_state[momentum_buffer]# buf buf*momentum 1-dampening*d_pbuf.mul_(momentum).add_(1-dampening,d_p)ifnesterov:# 使用neterov动量# d_p d_p momentum*bufd_pd_p.add(momentum,buf)else:d_pbuf# p p - lr*d_pp.data.add_(-group[lr],d_p)returnloss8 学习率衰减策略余弦退火衰减这可以理解为是一种带重启的随机梯度下降算法。在网络模型更新时由于存在很多局部最优解这就导致模型会陷入局部最优解即优化函数存在多个峰值。这就要求当模型陷入局部最优解时能够跳出去并且继续寻找下一个最优解直到找到全局最优解。要使得模型跳出局部最优解就需要在模型陷入局部最优解时突然提高学习率即重启学习率。多周期的余弦退火衰减示意图如下相关代码实现# ----------------------------------------------------------------------- ## 多周期余弦退火衰减# ----------------------------------------------------------------------- ## eager模式防止graph报错tf.config.experimental_run_functions_eagerly(True)# ------------------------------------------------ #importmath# 继承自定义学习率的类classCosineWarmupDecay(keras.optimizers.schedules.LearningRateSchedule): initial_lr: 初始的学习率 min_lr: 学习率的最小值 max_lr: 学习率的最大值 warmup_step: 线性上升部分需要的step total_step: 第一个余弦退火周期需要对总step multi: 下个周期相比于上个周期调整的倍率 print_step: 多少个step并打印一次学习率 # 初始化def__init__(self,initial_lr,min_lr,warmup_step,total_step,multi,print_step):# 继承父类的初始化方法super(CosineWarmupDecay,self).__init__()# 属性分配self.initial_lrtf.cast(initial_lr,dtypetf.float32)self.min_lrtf.cast(min_lr,dtypetf.float32)self.warmup_stepwarmup_step# 初始为第一个周期的线性段的stepself.total_steptotal_step# 初始为第一个周期的总stepself.multimulti self.print_stepprint_step# 保存每一个step的学习率self.learning_rate_list[]# 当前步长self.step0# 前向传播, 训练时传入当前step但是上面已经定义了一个这个step用不上def__call__(self,step):# 如果当前step达到了当前周期末端就调整ifself.stepself.total_step:# 乘上倍率因子后会有小数这里要注意# 调整一个周期中线性部分的step长度self.warmup_stepself.warmup_step*(1self.multi)# 调整一个周期的总step长度self.total_stepself.total_step*(1self.multi)# 重置step从线性部分重新开始self.step0# 余弦部分的计算公式decayed_learning_rateself.min_lr0.5*(self.initial_lr-self.min_lr)*\(1tf.math.cos(math.pi*(self.step-self.warmup_step)/\(self.total_step-self.warmup_step)))# 计算线性上升部分的增长系数kk(self.initial_lr-self.min_lr)/self.warmup_step# 线性增长线段 ykxbwarmupk*self.stepself.min_lr# 以学习率峰值点横坐标为界左侧是线性上升右侧是余弦下降decayed_learning_ratetf.where(self.stepself.warmup_step,warmup,decayed_learning_rate)# 每个epoch打印一次学习率ifstep%self.print_step0:# 打印当前step的学习率print(learning_rate has changed to: ,decayed_learning_rate.numpy().item())# 每个step保存一次学习率self.learning_rate_list.append(decayed_learning_rate.numpy().item())# 计算完当前学习率后step加一用于下一次self.stepself.step1# 返回调整后的学习率returndecayed_learning_rate篇幅有限更多详细设计见设计论文9 最后项目包含内容近3万字 完整详细设计论文项目分享见主页任意置顶文章

相关新闻

如何解决 publish-unit-test-result-action 常见错误:权限问题与配置陷阱

如何解决 publish-unit-test-result-action 常见错误:权限问题与配置陷阱

如何解决 publish-unit-test-result-action 常见错误:权限问题与配置陷阱 【免费下载链接】publish-unit-test-result-action GitHub Action to publish unit test results on GitHub 项目地址: https://gitcode.com/gh_mirrors/pu/publish-unit-test-result-acti…

2026/7/21 17:26:13阅读更多 →
Stable-Baselines3 进阶教程:自定义策略网络与算法实现原理

Stable-Baselines3 进阶教程:自定义策略网络与算法实现原理

Stable-Baselines3 进阶教程:自定义策略网络与算法实现原理 【免费下载链接】rl-tutorial-jnrr19 Stable-Baselines tutorial for Journes Nationales de la Recherche en Robotique 2019 项目地址: https://gitcode.com/gh_mirrors/rl/rl-tutorial-jnrr19 …

2026/7/21 17:26:13阅读更多 →
DNS子域名长度限制介绍(子域名层级限制、域名标签长度限制)

DNS子域名长度限制介绍(子域名层级限制、域名标签长度限制)

文章目录DNS 子域名层级限制技术规范(RFC 1035)实际例子实际使用建议实际限制因素DNS 子域名层级限制 从技术角度和实际使用两个层面来看: 技术规范(RFC 1035) 限制项数值说明单个标签(Label&#xff09…

2026/7/21 17:26:13阅读更多 →
鸿蒙 ArkTS 实战:Community Medicine Pickup 从社区代买药到社区便民应用完整解析

鸿蒙 ArkTS 实战:Community Medicine Pickup 从社区代买药到社区便民应用完整解析

鸿蒙 ArkTS 实战:Community Medicine Pickup 从社区代买药到社区便民应用完整解析 前言 社区代买药 是一个贴近生活服务场景的鸿蒙 ArkTS 单页应用。它的源码并不复杂,却把状态驱动界面、列表循环渲染、条件样式、按钮事件和业务结果即时反馈都放在了一…

2026/7/21 22:12:36阅读更多 →
C语言30天速通:零基础到项目实战与就业接单指南

C语言30天速通:零基础到项目实战与就业接单指南

这次我们来看一个面向零基础小白的C语言速通学习路径。这个路径的核心目标很直接:用30天时间,从完全不懂到能够完成基础项目,并具备接单和求职的初步能力。它不是某个单一的软件或模型,而是一套整合了 基础语法、进阶案例、实战项…

2026/7/21 22:12:36阅读更多 →
鸿蒙 ArkTS 实战:Short Rental Cleaning 从房屋短租清洁到短租保洁应用完整解析

鸿蒙 ArkTS 实战:Short Rental Cleaning 从房屋短租清洁到短租保洁应用完整解析

鸿蒙 ArkTS 实战:Short Rental Cleaning 从房屋短租清洁到短租保洁应用完整解析 前言 房屋短租清洁 是一个贴近生活服务场景的鸿蒙 ArkTS 单页应用。它的源码并不复杂,却把状态驱动界面、列表循环渲染、条件样式、按钮事件和业务结果即时反馈都放在了一…

2026/7/21 22:12:36阅读更多 →
鸿蒙 ArkTS 实战:City Guide Schedule 从同城导游日程到本地旅行应用完整解析

鸿蒙 ArkTS 实战:City Guide Schedule 从同城导游日程到本地旅行应用完整解析

鸿蒙 ArkTS 实战:City Guide Schedule 从同城导游日程到本地旅行应用完整解析 前言 同城导游日程 是一个典型的鸿蒙 ArkTS 小型业务应用,页面体量不大,但覆盖了状态驱动界面、列表渲染、条件文案、按钮事件和业务数据即时反馈这些移动端开发…

2026/7/21 22:12:36阅读更多 →
Unity开发避坑指南:资源管理、生命周期与平台适配实战解析

Unity开发避坑指南:资源管理、生命周期与平台适配实战解析

1. 项目概述:为什么我们需要一份“踩坑记录”?做Unity游戏开发,时间长了你会发现一个有趣的现象:项目初期,大家热情高涨,功能实现飞快;但到了中后期,尤其是临近上线或者团队规模扩大…

2026/7/21 22:12:36阅读更多 →
【JAVA毕设源码分享】基于springboot救援物资管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot救援物资管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/21 22:10:35阅读更多 →
Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 0:51:49阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 0:51:49阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 0:51:49阅读更多 →
Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

Windows+macOS 通用 OpenClaw 部署流程,内置依赖一键启动智能桌面助手

📌教程适配:OpenClaw v2.7.9 | 兼容 Windows10/11、macOS 双系统 📖前言 当下各类本地 AI 工具层出不穷,多数产品仅能完成文字问答交互,很难直接操控电脑执行实际操作。OpenClaw,业内常称小龙虾 AI&#…

2026/7/21 0:01:46阅读更多 →
Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

Codex 接入后 Bug 反增?复盘从个人演示到团队协作的“流程陷阱”

聊《一次Codex项目复盘,问题最后出在流程而不是模型》之前,先说一句实在的:别急着背概念,先看它在真实项目里到底解决什么问题。摘要先把这篇文章的目标说清楚:看完之后,你应该能判断这件事值不值得做&…

2026/7/21 0:01:46阅读更多 →
手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

手把手搓一个五子棋游戏,零代码也能当“游戏开发者”

大家好,还是我。前几期带大家做了心情日记本和可视化大屏,后台有朋友留言:“能不能教点好玩的?我想做游戏,但一行代码都不会。”行,这期就安排。今天的目标:从零做一个五子棋游戏。 带AI对战、三…

2026/7/21 0:03:46阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/20 22:51:39阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/21 18:53:30阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/21 18:53:30阅读更多 →