又把她拍丑了?试试蒙太奇风格给照片提高一个逼格吧~

文章目录

  • 转蒙太奇风格
    • 准备工作
    • 预处理
    • 计算每张素材图像的直方图
    • 匹配&替换
    • 加权混合
    • 完整代码
  • 狗粮

还在想这次活动做什么的时候, 偶尔发现了手机里很早之前给npy拍的照片, 那叫一个丑啊…删又不舍得, 想了想打算给它做一点处理, 也就想到了蒙太奇风格

转蒙太奇风格

准备工作

这里我们需要目标图像target.jpg, "精挑细选"一张npy的照片, 另外很多素材图像, 理论上可以是任意的图像. 但是为了更有意义, 可以选择旅游照啊, 自拍啊啥的和npy有关的. 我这里为了方便就选择了lfw人脸数据集, 下载链接在这

准备好这些图像那准备工作就完成了

预处理

接着需要对target.jpg和素材图象做一些预处理, 要做的事情如下:

  • 统计素材的数量, 将素材也调整大小到一个合适的值. 假设有13000张素材, 而target.jpg的大小是1080x1440, 那么选取10000张(估算时需要预留一部分以免素材匹配不上不够用)来拼成target.jpg的话, 每张素材的大小大概是10.8x14.4, 也就是10x15
  • target.jpg调整大小到一个合理的值, 使得长宽刚好能被调整后的素材大小整除, 比如针对上面的10x15的大小, 应该将1081x1445target.jpg调整到1080x1440

opencvresize函数可以方便地调整图像大小, 借助os库, 可以对一个目录下的所有文件进行该操作:

def gen_all_images_src(self):
    """
    将数据集中的所有jpg图像resize到25x25并存入DIR_IMAGES_SRC
    """
    self.log_string('>> gen_all_images_src ...')
    cnt = 0
    for dir_cur in os.listdir(self.__DIR_DATASET):
        self.log_string('>> extracting from {}'.format(os.path.join(self.__DIR_DATASET, dir_cur)))
        for file in os.listdir(os.path.join(self.__DIR_DATASET, dir_cur)):
            self.log_string('>> detected files: ' + str(os.listdir(os.path.join(self.__DIR_DATASET, dir_cur))))
            img = cv.imread(os.path.join(self.__DIR_DATASET, dir_cur) + '/' + file)
            save_name = self.__DIR_IMAGES_SRC + 'image-{}.jpg'.format(cnt)
            img_resized = cv.resize(img, (20, 20))
            self.log_string('>> writing to {}'.format(save_name))
            cv.imwrite(save_name, img_resized)
            cnt += 1

    self.log_string('>> gen_all_images_src done! \n\n\n')

做完这两步那预处理也完成了

计算每张素材图像的直方图

同样, 直接调用opencvcalcHist函数就好, 为方便后续使用, 将所有素材的直方图结果存入一个dict字典, key为素材的路径, value为素材的直方图

def gen_hist_dict(self):
    """
    统计所有images_src的直方图并保存
    :return:
    """
    self.log_string('>> calculating hist ...')
    hist_dict = {
     }

    for file in os.listdir(self.__DIR_IMAGES_SRC):
        img = cv.imread(os.path.join(self.__DIR_IMAGES_SRC, file))
            hist = []
        for i in range(3):
            ht = cv.calcHist([img], [i], None, [256], [0, 256])
            hist.append(ht)
        hist_dict[file] = hist

    self.log_string('>> calculating hist done ! \n\n\n')
    self.__hist_dict = hist_dict

匹配&替换

target.jpg划分成若干个区域, 对每个区域做暴力匹配. 比如target.jpg大小为1080x1440, 素材大小是10x15, 那么也就是将target.jpg划分成108x96个区域, 对这些区域做暴力匹配:

  • 计算每个区域的直方图
  • 从前一步的直方图字典中, 找到契合度最大的一个素材
  • 将这个区域替换成这个素材
def match_replace(self):
    """
    将素材拼成目标图像
    """
    self.log_string(">> matching and replacing ...")
    height, width, channel = self.__TARGET_SHAPE
    image_target = deepcopy(self.__image_target)

    dy, dx = self.__RESIEZE_SHAPE

    for i in range(0, height, dy):
        for j in range(0, width, dx):
            img = image_target[i:i + dy, j:j + dx, 0:3]

            hist = []
            for k in range(3):
                ht = cv.calcHist([img], [k], None, [256], [0, 256])
                hist.append(ht)
            rename = 0
            sim = 0.0
            for key in self.__hist_dict:
                match0 = cv.compareHist(hist[0], self.__hist_dict[key][0], cv.HISTCMP_CORREL)
                match1 = cv.compareHist(hist[1], self.__hist_dict[key][1], cv.HISTCMP_CORREL)
                match2 = cv.compareHist(hist[2], self.__hist_dict[key][2], cv.HISTCMP_CORREL)
                match = match0 + match1 + match2

                if match >= sim:
                    sim = match
                    rename = key
            if i + dy <= height and j + dx <= width:
                image_target[i:i + dy, j:j + dx, 0:3] = cv.imread(os.path.join(self.__DIR_IMAGES_SRC, rename))

    cv.imwrite(os.path.join(self.__DIR_IMAGES, 'generate.jpg'), image_target)
    self.log_string('>> matching and replacing done ! \n\n\n ')

其中需要注意的是, 同一幅图像,操作系统中显示的大小是1080x1440, 但是在opencv里面的shape1440x1080, 两个轴是反的.

得到generate.jpg就算大功告成了, 至此我们已经完成了图像风格的蒙太奇转换, 但是效果还不是很理想, 如下:

又把她拍丑了?试试蒙太奇风格给照片提高一个逼格吧~_第1张图片

加权混合

因此我们将target.jpggenerate.jpg做一个加权平均:

def mixup(self):
    """
    将生成的图像与目标图像做mixup,得到更好的效果
    """
    self.log_string('mixing ...')
    image1 = self.__image_target
    image2 = cv.imread(os.path.join(self.__DIR_IMAGES, 'generate.jpg'))
    dst = cv.addWeighted(image1, 0.2, image2, 0.8, 3)
    cv.imwrite(os.path.join(self.__DIR_IMAGES, 'mixed.jpg'), dst)
    self.log_string('mixing done ! \n\n\n')

得到的效果明显好很多:

又把她拍丑了?试试蒙太奇风格给照片提高一个逼格吧~_第2张图片

完整代码

等审核通过后点击下载链接即可下载
加上argparse后封装好的hithub链接在这:
git clone https://github.com/poorCodingMan/MontageTransform.git

狗粮

该来的总会来的…

Every once in a while you find someone who’s iridescent, and when you do, nothing will ever compare. --


你可能感兴趣的:(其它,opencv,图像处理,图像风格转换,蒙太奇,python)