【学习记录】图片局部放大

这篇博客介绍了如何使用OpenCV实现图像的局部放大,并提供了两种方法:一种是将放大区域放置在原图内部,另一种是拼接到原图侧面。还详细解释了函数实现过程,并给出了主函数示例。此外,文中还添加了目标区域的直观选取功能,通过鼠标交互选取需要放大的区域,提高了操作的便捷性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面:本博客仅作记录学习之用,部分图片来自网络,如需使用请注明出处,同时如有侵犯您的权益,请联系删除!

前言

本博客仅为学习记录之用,目的在于后续若需要相关的有资可查。在言语上恐有诸多纰漏,如有错误,欢迎指出交流学习!
本博客所包含的大致内容: 图片某一局部放大并置于图形内部;图片多个局部放大并拼接在原图侧面。


局部放大

为什么要局部放大?无论的图像生成、修复、去污等等,如生成对抗方法;亦或是图像分割,如unet。对于方法的结果都需要进行有效的展示,凸显方法的优越性能,往往细节的部分才是我们所更加关注的。但往往在图像本身很难观察到这些细节,因此有意识的将需要的局部放大是展示效果的有效方法。


函数实现


单一局部放大置于图像内部

思路也简单,首先获取到需要关注的部分,然后在将其进行插值放大,最后放在原图的某一位置即可。

本函数参数传入图像,需要目标区域的指标,其次放在的位置,支持四个角以及中心,以及放大的倍数。
目标区域为矩形,长宽比任意。


def Partial_magnification(pic, target, location='lower_right', ratio=1):
    '''
    :param pic: input pic
    :param target: Intercept area, for example [target_x, target_y, target_w, target_h]
    :param location: lower_right,lower_left,top_right,top_left,center
    :param ratio: gain
    :return: oringal pic, pic
    '''
    img = copy.copy(pic)

    w, h = pic.shape[1], pic.shape[0],

    target_x, target_y = target[0], target[1]
    target_w, target_h = target[2], target[3]
    cv2.rectangle(pic, (target_x, target_y), (target_x + target_w, target_y + target_h), (255, 255, 0), 2)
    new_pic = pic[target_y:target_y + target_h, target_x:target_x + target_w]
    new_pic = cv2.resize(new_pic, (target_w*ratio, target_h*ratio), interpolation=cv2.INTER_CUBIC)
    if location == 'lower_right':
        pic[h-1-target_h*ratio:h-1, w-1-target_w*ratio:w-1] = new_pic
        cv2.line(pic, (target_x + target_w, target_y + target_h), (w-1-target_w*ratio, h-1-target_h*ratio), (255, 0, 0),2)
    elif location == 'lower_left':
        pic[h-1-target_h*ratio:h-1, 0:target_w*ratio] = new_pic
    elif location == 'top_right':
        pic[0:target_h*ratio, w-1-target_w*ratio:w-1] = new_pic
    elif location == 'top_left':
        pic[0:target_h*ratio, 0:target_w*ratio] = new_pic
    elif location == 'center':
        pic[int(h/2-target_h*ratio/2):int(h/2+target_h*ratio/2),
            int(w/2-target_w*ratio/2):int(w/2+target_w*ratio/2)] = new_pic
    return img, pic

多局部放大拼接于图形侧面

当存在多个局部需要放大时,若都置于原图内部,遮挡图片内容的可能性较大,因此将其置于图像侧面。

本函数仅支持两个局部区域放大。和第一个函数不同的是两个局部放大的区域长宽比需要一致,为了方便拼接。没有设置放大倍数,默认局部放大后拼接图片与原图等高。


def Partial_magnification_2(pic, target1, target2, *args):
    '''
    :param pic: input pic
    :param target: Intercept area, for example [target_x, target_y, target_w, target_w]
    :param location: lower_right,lower_left,top_right,top_left,center
    :param ratio: gain
    :return: oringal pic, pic
    '''
    # imgg = copy.copy(pic)
    w, h = pic.shape[1], pic.shape[0],

    assert target1[0]+target1[2] < w and target1[1]+target1[3] < h,\
        'The target1 area is too large and exceeds the image size'
    assert target2[0]+target2[2] < w and target2[1]+target2[3] < h,\
        'The target2 area is too large and exceeds the image size'

    assert target1[2] > 10 or target1[3] > 10, \
        'The target1 area is too small, not recommended'
    assert target2[2] > 10 or target2[3] > 10, \
        'The target2 area is too small, not recommended'

    assert target1[0] > 0 and target1[0] < w, \
        'The starting point of the target1 area is beyond the scope of the image'
    assert target2[0] > 0 and target2[0] < w, \
        'The starting point of the target2 area is beyond the scope of the image'

    if target2[2] / target2[3] == target1[2] / target1[3]:  #
        R = target2[2]/target2[3]
        if target1[1] > target2[1]:
            target1_x, target1_y = target2[0], target2[1]
            target1_w, target1_h = target2[2], target2[3]

            target2_x, target2_y = target1[0], target1[1]
            target2_w, target2_h = target1[2], target1[3]

        else:
            target1_x, target1_y = target1[0], target1[1]
            target1_w, target1_h = target1[2], target1[3]

            target2_x, target2_y = target2[0], target2[1]
            target2_w, target2_h = target2[2], target2[3]

        cv2.rectangle(pic, (target1_x, target1_y), (target1_x + target1_w, target1_y + target1_h), (255, 250, 255), 2)
        cv2.rectangle(pic, (target2_x, target2_y), (target2_x + target2_w, target2_y + target2_h), (255, 252, 255), 2)

        new_pic1 = pic[target1_y:target1_y + target1_h, target1_x:target1_x + target1_w]
        new_pic1 = cv2.resize(new_pic1, (int(h//2 * R), h//2), cv2.INTER_CUBIC)

        new_pic2 = pic[target2_y:target2_y + target2_h, target2_x:target2_x + target2_w]
        new_pic2 = cv2.resize(new_pic2, (int(h//2 * R), h//2))

        img = np.zeros((h, int(h//2 * R), 3), np.uint8)
        img[0:h//2, 0:int(h//2 * R)] = new_pic1
        img[h//2:h, 0:int(h//2 * R)] = new_pic2

        hmerge = np.hstack((pic, img))
        cv2.line(hmerge, (target1_x + target1_w, target1_y), (w, 0), (255, 255, 255), 2)
        cv2.line(hmerge, (target2_x + target2_w, target2_y + target2_h), (w, h), (255, 255, 255), 2)
        return  hmerge
    else:
        raise ValueError('Make sure the aspect ratio of target is consistent !')


主函数


为方便复现提供了参考的主程序,如果需要批量放大,添加循环即可。


if __name__ == '__main__':
    img = cv2.imread(r'./test/Image_11L.jpg')  
    target1 = [250, 250, 100, 100]
    pic, pic1 = Partial_magnification(img, target1, location='lower_right', ratio=4)
    target2 = [180, 400, 100, 50]
    pic, pic2 = Partial_magnification(pic, target2, location='lower_left', ratio=2)
    hmerge = np.hstack((pic1, pic2))

    if max(hmerge.shape[0], hmerge.shape[1]) > 1000:
        # cv2.namedWindow('merge', 0)
        # cv2.resizeWindow('merge', 1000, int(1000*hmerge.shape[0]/hmerge.shape[1]))
        # cv2.imshow('merge', hmerge)
        # cv2.waitKey(0)
        # cv2.destroyAllWindows()
        hmerge = cv2.cvtColor(hmerge, cv2.COLOR_BGR2RGB)
        fig = plt.figure(figsize=(40, 20))  # figsize 尺寸
        plt.imshow(hmerge)
        plt.savefig('aaa_bbb.png', dpi=200)  # dpi分辨率
        plt.show()
    else:
        plt.imshow(hmerge)
        plt.show()
if __name__ == '__main__':
    img = cv2.imread(r'./test/Image_11L.jpg')  
    target1 = [250, 650, 100, 100]
    target2 = [450, 400, 100, 100]
    pic1 = Partial_magnification_2(img, target1, target2)

    hmerge = cv2.cvtColor(pic1, cv2.COLOR_BGR2RGB)
    fig = plt.figure(figsize=(30, 20))
    fig.patch.set_facecolor('gray')
    plt.imshow(hmerge)
    plt.savefig('aaa_bbb.png', dpi=300, bbox_inches='tight')
    plt.show()

效果


以下是两个函数的测试结果,主程序如上。


在这里插入图片描述

在这里插入图片描述


目标区域选取的方法

上述的目标的指定放大的区域全靠大致位置加不断调整,使得绘图不够直观的准确,今添加选取指定区域的方法,利用opencv 直接直观的选取指定区域。

目标区域选取程序

def on_EVENT_change(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        point.append((x, y))
        target.append((x, y))
        xy = "%d,%d" % (x, y)
        cv2.circle(copyImg, (x, y), 1, (255, 0, 0), thickness=-1)
        cv2.putText(copyImg, xy, (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.0, (0, 0, 0), thickness=1)
        cv2.imshow("image", copyImg)
    elif event == cv2.EVENT_LBUTTONUP:
        point.append((x, y))
        target.append((x, y))
        xy = "%d,%d" % (x, y)
        cv2.rectangle(copyImg, point[0], point[1], (0, 255, 0), thickness=1, lineType=8, shift=0)
        cv2.circle(copyImg, (x, y), 1, (255, 0, 0), thickness=-1)
        cv2.putText(copyImg, xy, (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.0, (255, 0, 0), thickness=1)
        cv2.imshow("image", copyImg)
        point.clear()
    elif event == cv2.EVENT_RBUTTONDOWN:
        cv2.imshow("image", img)
        cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)


def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        point.append((x, y))
        target.append((x, y))
        xy = "%d,%d" % (x, y)
        cv2.circle(img, (x, y), 1, (255, 0, 0), thickness=-1)
        cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.0, (0, 0, 0), thickness=1)
        cv2.imshow("image", img)
    elif event == cv2.EVENT_LBUTTONUP:
        point.append((x, y))
        target.append((x, y))
        xy = "%d,%d" % (x, y)
        cv2.rectangle(img, point[0], point[1], (0, 255, 0), thickness=1, lineType=8, shift=0)
        cv2.circle(img, (x, y), 1, (255, 0, 0), thickness=-1)
        cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1.0, (255, 0, 0), thickness=1)
        cv2.imshow("image", img)
        point.clear()
    elif event == cv2.EVENT_RBUTTONDOWN:
        cv2.imshow("image", copyImg)
        cv2.setMouseCallback("image", on_EVENT_change)


if __name__ == '__main__':  #Partial_magnification
# point、target、img、"image"不能修改,和前文定义函数绑定
    point = []
    target = []
    path = "xxx.jpg"
    img = cv2.imread(path)
    copyImg = copy.deepcopy(img)
    cv2.namedWindow("image")
    cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)
    cv2.imshow("image", img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    location = ['top_left', 'top_right', 'lower_right', 'lower_left', 'center']
    img = cv2.imread(path)  # C:\Users\Administrator\Desktop\dd.jpg
    for i in range(len(target)//2):
        if target[2*i+1][0]-target[2*i][0]>0:
            target1 = [target[2*i][0], target[2*i][1], target[2*i+1][0]-target[2*i][0], target[2*i+1][1]-target[2*i][1]]
        else:
            raise ValueError('请从左往右,从下往上 框取区域')
        if i == 0:
            pic, pic1 = Partial_magnification(img, target1, location=location[i], ratio=2)
        else:
            pic, pic1 = Partial_magnification(pic, target1, location=location[i], ratio=2)

    fig = plt.figure(figsize=(20, 20))  # figsize 尺寸
    plt.imshow(cv2.cvtColor(pic, cv2.COLOR_BGR2RGB))
    plt.savefig('xxx.png', dpi=300, bbox_inches='tight')  # dpi 分辨率
    plt.show()

目标区域选取效果

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

使用说明

cv2上选取区域需要从左往右,从下往上 框取区域(局部放大函数的限制),最多五个区域(放大后的区域选项决定。如果选取区域在一个图相交,影响选取时右键使用备份绘制。


总结


以上就是本文的主要内容,都是OpenCV和plt的基本使用上实现图像的局部放大。


修改记录


2022.10.17 : 添加目标区域选取的方法


致谢

欲尽善本文,因所视短浅,怎奈所书皆是瞽言蒭议。行文至此,诚向予助与余者致以谢意。

实现Python图像局部细节放大,可以使用OpenCV库。以下是一种实现方法: 1. 导入必要的库和模块,例如cv2和sys。 2. 读取图像并判断是否成功读取。 3. 指定需要放大区域,可以通过裁剪图像来选择感兴趣的区域。 4. 使用双线性插值法将选定的区域进行放大,可以使用cv2.resize函数实现。设置放大后的大小和插值方式。 5. 将放大后的结果放置在图像的指定位置,可以通过赋值操作来实现。 6. 可选:为放大区域绘制边框和连线,以突出显示。 7. 展示最终的结果图像。 下面是实现局部细节放大Python代码示例: import cv2 as cv import sys if __name__ == '__main__': # 读取图像并判断是否读取成功 img = cv.imread('tu.jpg') if img is None: print('Failed to read picture') sys.exit() # 需要放大区域 part = img[300:400, 250:350] # 双线性插值法放大区域 mask = cv.resize(part, (300, 300), fx=0, fy=0, interpolation=cv.INTER_LINEAR) # 放大局部图的位置 img[110:410, 570:870] = mask # 画框并连线 cv.rectangle(img, (250, 300), (350, 400), (0, 255, 0), 1) img = cv.line(img, (350, 300), (570, 110), (0, 255, 0)) img = cv.line(img, (350, 400), (570, 410), (0, 255, 0)) # 展示结果 cv.imshow('img', img) cv.waitKey(0) cv.destroyAllWindows() 注意:在代码中,你需要将'tu.jpg'替换为你实际使用的图像文件路径。此代码将选定的区域放大,并将结果放置在图像的指定位置。你还可以根据需要调整参数来获得更好的效果。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [科研作图-局部图像放大效果的python实现](https://blog.csdn.net/zzu_zhong/article/details/131312317)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [python放大局部图像(画中画形式展示)](https://blog.csdn.net/qq_33687272/article/details/121363358)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东荷新绿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值