草庐IT

python - 我如何通过仿射变换在 opencv 中实现这一点?

coder 2023-08-14 原文

我想知道如何复制这张图片中正在做的事情:

分解:

  1. 使用 dlib(绿点)获取面部特征
  2. 旋转图像,使眼睛水平
  3. 通过平均最左边和最右边的界标(蓝点)找到面部的中点,并将图像放在 x 轴上居中
  4. 通过将眼睛中心放置在距离图像顶部 45% 的位置,将嘴巴中心放置在距离图像顶部 25% 的位置来固定沿 y 轴的位置

现在这就是我所拥有的:

我有点卡在第 3 步,我认为这可以通过仿射变换来完成吗?但是我完全被第 4 步难住了,我不知道如何实现它。

如果您需要我提供代码,请告诉我!

编辑:所以在看了@Gal Dreiman 的回答后,我能够将脸部完美地居中,这样蓝点就在我的图像的中心。

虽然当我实现他的回答的第二部分时,我最终得到了这样的结果:

我看到这些点已经被转换到正确的位置,但这并不是我想要的结果,因为它的倾斜非常明显。有什么想法吗?

编辑 2:

交换中心点的 x、y 坐标后,这就是我得到的:

最佳答案

正如我在第 3 部分看到的那样,最简单的方法是:

  1. 找出图片中的人脸:

    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(30, 30),
        flags = cv2.cv.CV_HAAR_SCALE_IMAGE
    )
    
  2. 为每个面计算中点:

    for (x, y, w, h) in faces:
        mid_x = x + int(w/2)
        mid_y = y + int(h/2)
    
  3. 仿射变换图像使您已经计算出的蓝点居中:

    height, width = img.shape
    x_dot = ...
    y_dot = ...
    
    dx_dot = int(width/2) - x_dot
    dy_dot = int(height/2) - y_dot
    
    M = np.float32([[1,0,dx_dot],[0,1,dy_dot]])
    dst = cv2.warpAffine(img,M,(cols,rows))
    

希望对您有所帮助。

编辑:

关于第 4 节: 为了拉伸(stretch)(调整大小)图像,您所要做的就是执行仿射变换。为了找到变换矩阵,我们需要输入图像中的三个点及其在输出图像中的对应位置。

    p_1 = [eyes_x, eye_y]
    p_2 = [int(width/2),int(height/2)] # default: center of the image
    p_3 = [mouth_x, mouth_y]

    target_p_1 = [eyes_x, int(eye_y * 0.45)]
    target_p_2 = [int(width/2),int(height/2)] # don't want to change
    target_p_3 = [mouth_x, int(mouth_y * 0.75)]

    pts1 = np.float32([p_1,p_2,p_3])
    pts2 = np.float32([target_p_1,target_p_2,target_p_3])

    M = cv2.getAffineTransform(pts1,pts2)

    output = cv2.warpAffine(image,M,(height,width))

清除事物:

  1. eye_x/eye_y 是眼睛中心的位置。
  2. 这同样适用于 mouth_x/mouth_y,用于嘴中心。
  3. target_p_1/2/3 是目标点。

编辑 2: 我看你有麻烦了,希望这次我的建议对你有用:

我能想到另一种方法。您可以通过指向 4 个点对图像进行某种“裁剪”,让我们将它们定义为包裹脸部的 4 个点,并根据它们的新位置更改图像透视图:

up_left = [x,y]
up_right = [...]
down_left = [...]
down_right = [...]

pts1 = np.float32([up_left,up_right,down_left,down_right])
pts2 = np.float32([[0,0],[300,0],[0,300],[300,300]])

M = cv2.getPerspectiveTransform(pts1,pts2)

dst = cv2.warpPerspective(img,M,(300,300))

所以您所要做的就是定义这 4 个点。我的建议是,计算面部周围的轮廓(您已经这样做了),然后将 delta_xdelta_y(或减去)坐标添加。

关于python - 我如何通过仿射变换在 opencv 中实现这一点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43042275/

有关python - 我如何通过仿射变换在 opencv 中实现这一点?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  4. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  5. ruby - 在 Ruby 中实现 `call_user_func_array` - 2

    我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)

  6. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 通过 rvm 升级 ruby​​gems 的问题 - 2

    尝试通过RVM将RubyGems升级到版本1.8.10并出现此错误:$rvmrubygemslatestRemovingoldRubygemsfiles...Installingrubygems-1.8.10forruby-1.9.2-p180...ERROR:Errorrunning'GEM_PATH="/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/ruby-1.9.2-p180@global:/Users/foo/.rvm/gems/ruby-1.9.2-p180:/Users/foo/.rvm/gems/rub

  9. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐