【问题标题】:How make eye and nose bigger or smaller in opencv and python如何在opencv和python中使眼睛和鼻子变大或变小
【发布时间】:2021-12-25 10:52:23
【问题描述】:

我使用以下代码在 OpenCV 和 Python 中选择鼻子我搜索了很多以找到改变鼻子大小并保存为其他图像的方法,但我没有找到任何东西有没有人可以帮助我这样做。

import cv2
import numpy as np
import dlib
img = cv2.imread('1.jpg')
img = cv2.resize(img,(0,0),None,0.5,0.5)
imgOriginal = img.copy()

detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

def createBox(img,points,scale=5):
  bbox = cv2.boundingRect(points)
  x,y,w,h = bbox
  imgCrop = img[y:y+h,x:x+w]
  imgCrop = cv2.resize(imgCrop,(0,0),None,scale,scale)
  return imgCrop


imgGray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
faces = detector(imgGray)
for face in faces:
  x1,y1 = face.left(),face.top()
  x2,y2 = face.right(),face.bottom()
  imgOriginal = cv2.rectangle(img,(x1,y1),(x2,y2),(0,255,0),1)
  landmarks = predictor(imgGray,face)
  myPoints=[]
  for n in range(68):
    x = landmarks.part(n).x
    y = landmarks.part(n).y
    myPoints.append([x,y])
    #cv2.circle(imgOriginal,(x,y),5,(50,50,255),cv2.FILLED)
    #cv2.putText(imgOriginal,str(n),(x,y-10),cv2.FONT_HERSHEY_COMPLEX_SMALL,0.8,(0,0,255),1)
  myPoints = np.array(myPoints)
  #nose points to select
  #nose_points = myPoints[27:35]

print(myPoints)
cv2_imshow(imgOriginal)
cv2.waitKey(0)


提前致谢

【问题讨论】:

    标签: python opencv image-processing dlib


    【解决方案1】:

    我认为您需要“膨胀”效果,例如内爆和爆炸。在 OpenCV 中没有这些过滤器的实现,但是您可以找到其他工具,例如 Wand(ImageMagick 的 Python 绑定),它们具有 implode/explode

    示例(魔杖):

    from wand.image import Image
    
    with Image(filename="test.jpg") as img:
        img.implode(amount = -0.2)
        img.save(filename="destination.jpg")
        # img_array = numpy.asarray(img) --> you can convert wand.image.Image to numpy array for further uses
    

    将负值传递给 implode 函数等同于进行爆炸。所以为了放大效果使用负值。

    但有一个问题:img.implode 在图像的中心执行,因此在找到面部特征(眼睛、鼻子……)后,您需要以某种方式移动图片以制作眼睛或鼻子位于图像的中心。之后,您可以简单地使用 implode 函数。

    【讨论】:

      【解决方案2】:

      这是在 Python/OpenCV 的局部区域中使用球形(气泡)扭曲的一种方法。

       - Define region center and radius and amount of spherical distortion
       - Crop the image for that center and radius
       - Compute the spherical distortion x and y displacement maps and a binary mask
       - Apply the distortion maps using cv2.remap
       - Antialias the mask
       - Merge the distorted and cropped image using the mask
       - Insert that merged image into the original image
       - Save the results
      

      输入:

      import numpy as np
      import cv2
      import math
      import skimage.exposure
      
      img = cv2.imread("portrait_of_mussorgsky2.jpg")
      
      # set location and radius
      cx = 130
      cy = 109
      radius = 30
      
      # set distortion gain
      gain = 1.5
      
      # crop image 
      crop = img[cy-radius:cy+radius, cx-radius:cx+radius]
      
      # get dimensions
      ht, wd = crop.shape[:2]
      xcent = wd / 2
      ycent = ht / 2
      rad = min(xcent,ycent)
      
      # set up the x and y maps as float32
      map_x = np.zeros((ht, wd), np.float32)
      map_y = np.zeros((ht, wd), np.float32)
      mask = np.zeros((ht, wd), np.uint8)
      
      # create map with the spherize distortion formula --- arcsin(r)
      # xcomp = arcsin(r)*x/r; ycomp = arsin(r)*y/r
      for y in range(ht):
          Y = (y - ycent)/ycent
          for x in range(wd):
              X = (x - xcent)/xcent
              R = math.hypot(X,Y)
              if R == 0:
                  map_x[y, x] = x
                  map_y[y, x] = y
                  mask[y,x] = 255
              elif R >= .90:    # avoid extreme blurring near R = 1
                  map_x[y, x] = x
                  map_y[y, x] = y
                  mask[y,x] = 0
              elif gain >= 0:
                  map_x[y, x] = xcent*X*math.pow((2/math.pi)*(math.asin(R)/R), gain) + xcent
                  map_y[y, x] = ycent*Y*math.pow((2/math.pi)*(math.asin(R)/R), gain) + ycent
                  mask[y,x] = 255
              elif gain < 0:
                  gain2 = -gain
                  map_x[y, x] = xcent*X*math.pow((math.sin(math.pi*R/2)/R), gain2) + xcent
                  map_y[y, x] = ycent*Y*math.pow((math.sin(math.pi*R/2)/R), gain2) + ycent
                  mask[y,x] = 255
      
      # remap using map_x and map_y
      bump = cv2.remap(crop, map_x, map_y, cv2.INTER_LINEAR, borderMode = cv2.BORDER_CONSTANT, borderValue=(0,0,0))
      
      # antialias edge of mask
      # (pad so blur does not extend to edges of image, then crop later)
      blur = 7
      mask = cv2.copyMakeBorder(mask, blur,blur,blur,blur, borderType=cv2.BORDER_CONSTANT, value=(0))
      mask = cv2.GaussianBlur(mask, (0,0), sigmaX=blur, sigmaY=blur, borderType = cv2.BORDER_DEFAULT)
      h, w = mask.shape
      mask = mask[blur:h-blur, blur:w-blur]
      mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)
      mask = skimage.exposure.rescale_intensity(mask, in_range=(127.5,255), out_range=(0,1))
      
      # merge bump with crop using grayscale (not binary) mask
      bumped = (bump * mask + crop * (1-mask)).clip(0,255).astype(np.uint8)
      
      # insert bumped image into original
      result = img.copy()
      result[cy-radius:cy+radius, cx-radius:cx+radius] = bumped
      
      # save results
      cv2.imwrite("portrait_of_mussorgsky2_bump.jpg", result)
      
      # display images
      cv2.imshow('img', img)
      cv2.imshow('crop', crop)
      cv2.imshow('bump', bump)
      cv2.imshow('mask', mask)
      cv2.imshow('bumped', bumped)
      cv2.imshow('result', result)
      cv2.waitKey(0)
      cv2.destroyAllWindows()
      

      结果图像:

      【讨论】:

        猜你喜欢
        • 2019-04-29
        • 2012-02-19
        • 2017-01-15
        • 2016-10-08
        • 2015-05-02
        • 2015-09-06
        • 2019-12-29
        • 2012-03-14
        • 2018-05-02
        相关资源
        最近更新 更多