草庐IT

利用yolov5进行目标检测,并将检测到的目标裁剪出来

小脑斧ai吃肉 2023-08-09 原文

利用yolov5进行目标检测,并将检测到的目标裁剪出来

写在前面:关于yolov5的调试运行在这里不做过多赘述,有关yolov5的调试运行请看:https://www.bilibili.com/video/BV1tf4y1t7ru/spm_id_from=333.999.0.0&vd_source=043dc71f3eaf6a0ccb6dada9dbd8be37
本文章主要讲解的是裁剪。

需求:识别图片中的人物并将其裁剪出来

如果只需识别人物的话,那么只需在yolov5中设定参数即可,例如使用命令行运行时:python --classes 0
即为将参数设置为只识别人。此外需要将检测到的目标裁剪出来还需要目标的中心点坐标以及目标的宽高,因此需要保存目标的信息。实现人物检测并保存检测到的目标信息,运行命令为:python --classes0 --save-txt
在保存目标信息的tx文件中,例如下图:0 0.682078 0.495935 0.613014 0.99187,从左到右以此代表:目标类型(0代表person)、目标中心点坐标的x值(x_center),目标中心点坐标的y值(y_center),目标的宽度(width),目标的高度(height)。


要进行裁剪的条件是需要得到x1,x2,y1,y2。很显然

x1=x_center-width/2
x2=x_center+width/2
y1=y_center-height/2
y2=y_center+height/2

但是由于yolov5的txt文件中存储的x_center,y_center,width,height都是经过归一化处理的所以,上述公式中所计算得到的x1,x2,y1,y2值都是经过归一化处理之后的值,我们要的是原值,所以

x1=(x_center-width/2)*整张图片的宽度(注:是整张图片的宽度不是目标的宽度,这里的宽度就是像素宽度)
x2=(x_center+width/2)*整张图片的宽度
y1=(y_center-height/2)*整张图片的高度(注:是整张图片的高度不是目标的高度,这里的高度就是像素高度)
y2=(y_center+height/2)*整张图片的高度

得到了x1,x2,y1,y2四个值,那在水平方向上裁剪x1---->x2,在垂直方向上裁剪y1---->y2,即可。
代码实现:

import os
import cv2

def main():
	#图片路径
    img_path = './data/images/hg.jpg'
    #txt文件路径
    label_path = './runs/detect/exp23/labels/hg.txt'
    # 读取图片,结果为三维数组
    img = cv2.imread(img_path)
    # 图片宽度(像素)
    w = img.shape[1]
    # 图片高度(像素)
    h = img.shape[0]
    # 打开文件,编码格式'utf-8','r+'读写
    f = open(label_path, 'r+', encoding='utf-8')  
    # 读取txt文件中的第一行,数据类型str
    line = f.readline()
    # 根据空格切割字符串,最后得到的是一个list
    msg = line.split(" ")
    x1 = int((float(msg[1]) - float(msg[3]) / 2) * w)  # x_center - width/2
    y1 = int((float(msg[2]) - float(msg[4]) / 2) * h)  # y_center - height/2
    x2 = int((float(msg[1]) + float(msg[3]) / 2) * w)  # x_center + width/2
    y2 = int((float(msg[2]) + float(msg[4]) / 2) * h)  # y_center + height/2
    print(x1, ",", y1, ",", x2, ",", y2)
    #裁剪
    img_roi = img[y1:y2,x1:x2]
    save_path='./cutpictures/hg.jpg'
    cv2.imwrite(save_path,img_roi)

if __name__ == '__main__':  
    main() 

效果展示:
目标检测

裁剪

写在后面:在上面的代码实现中,因为我已经知道了在图片中只有一个person,所以txt文件中只有一行,所以我只用f.readlin()读取了一行,如果有多个目标person,那就用f.readlines()读取多行,再用for循环一行一行去裁剪即可。

更正:在后续的操作中我想把图片中最远的人裁剪出来,也就是下图的红框,那只需比较y_center,把y_center最大的裁剪出来即可,按照此想法我裁剪出来的却是绿框。

后来验证发现yolov中的坐标系如下:

但是并不影响对上面相关过程的理解。

有关利用yolov5进行目标检测,并将检测到的目标裁剪出来的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby - 如何进行排列以有效地定制输出 - 2

    这是一道面试题,我没有答对,但还是很好奇怎么解。你有N个人的大家庭,分别是1,2,3,...,N岁。你想给你的大家庭拍张照片。所有的家庭成员都排成一排。“我是家里的friend,建议家庭成员安排如下:”1岁的家庭成员坐在这一排的最左边。每两个坐在一起的家庭成员的年龄相差不得超过2岁。输入:整数N,1≤N≤55。输出:摄影师可以拍摄的照片数量。示例->输入:4,输出:4符合条件的数组:[1,2,3,4][1,2,4,3][1,3,2,4][1,3,4,2]另一个例子:输入:5输出:6符合条件的数组:[1,2,3,4,5][1,2,3,5,4][1,2,4,3,5][1,2,4,5,3][

  5. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  6. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

  7. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  8. ruby - 在 Windows 机器上使用 Ruby 进行开发是否会适得其反? - 2

    这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby​​-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub

  9. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  10. ruby - 如何跳过 CSV 文件的第一行并将第二行作为标题 - 2

    有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|

随机推荐