编写一个图片去水印的小工具

      原理分析

        为了便于分析原理,我写了一个简单的Demo,如下图所示,在Demo页面中有三张单色图片,第一张原始图是颜色为#999的灰色图片,第二张水印图是颜色为#fff透明度为0.7的图片,第三张结果图是前两张图片合成以后得到的图片。

        在右侧的控制台打印出了这三张图片的数据(数据是通过canvas画布中的getImageData方法获取到的),从数据中可以看到,三张图片的宽高均为100像素,数据长度均为40000。可以看出,每张图片有100*100个像素点,每个像素点用4个长度来表示,分别是R(红)、G(绿)、B(蓝)、A(透明度)。

        接下来,对比下三张图片数据有何不同,原图片和水印图的数据是怎么得到结果图的数据的?

        稍微想一下,应该可以得出一个思路:水印图的透明度为0.7,意味着它的色值在结果图中占的比重是70%,原始图因为被水印图遮挡,所以占的比重是剩余的30%。于是,153 × 0.3 + 255 × 0.7 = 224.4,向上取整后为225,正好与结果图中数据相等。

      功能实现

        实践是检验理论的唯一手段。根据上述猜测的计算方式,如果已知结果图和水印图,那么应该就可以推算出来原始图。不过需要准备好与待处理图片相对应的水印图片,确保它们的尺寸大小和水印位置是一致的,否则靠程序自己去猜测水印位置的话,需要额外复杂的算法和很大的计算量支撑。

        这里我设计的程序界面如下:

        程序上方是参数配置,可以设置水印图片和下载目录,左侧区域是待处理图片列表区,可以将待处理的图片拖拽进来,右侧区域是图片预览区域,点选左侧某一条数据可以对其进行预览。

        程序去水印的关键代码如下:

// 获取imgData
getImgData (imgObj) {
    let canvasObj = document.createElement('canvas')
    canvasObj.width = imgObj.width
    canvasObj.height = imgObj.height
    let ctx = canvasObj.getContext('2d')
    ctx.drawImage(imgObj, 0, 0, canvasObj.width, canvasObj.height)
    let imgData = ctx.getImageData(0, 0, canvasObj.width, canvasObj.height)
    return imgData.data
}
let imgData = this.imagesList[index].imgData
let imgData_sy = this.watermarkInfo.imgData
if (imgData.length !== imgData_sy.length) {
    this.$toast('待处理图片与水印图片大小不一致')
    return reject('待处理图片与水印图片大小不一致')
}
let bakColor = null
for (let i = imgData.length - 4; i > -1; i -= 4) {
    if (!imgData_sy[i + 3]) {
        bakColor = [imgData[i + 0], imgData[i + 1], imgData[i + 2], imgData[i + 3]]
        continue
    } else if (imgData_sy[i + 3] === 255 && bakColor) {
        imgData[i + 0] = bakColor[0]
        imgData[i + 1] = bakColor[1]
        imgData[i + 2] = bakColor[2]
        imgData[i + 3] = bakColor[3]
        continue
    }
    let opacity_sy = imgData_sy[i + 3] / 255
    let opacity_raw = (255 - imgData_sy[i + 3]) / 255
    imgData[i + 0] = (imgData[i + 0] - imgData_sy[i + 0] * opacity_sy) / opacity_raw
    imgData[i + 1] = (imgData[i + 1] - imgData_sy[i + 1] * opacity_sy) / opacity_raw
    imgData[i + 2] = (imgData[i + 2] - imgData_sy[i + 2] * opacity_sy) / opacity_raw
    if (imgData[i + 3] > 0 && imgData[i + 3] < 255) {
        imgData[i + 3] = (imgData[i + 3] - imgData_sy[i + 3]) / opacity_raw
    }
}
this.imagesList[index].imgData = imgData
// imgData2dataUrl
let canvasObj = document.createElement('canvas')
canvasObj.width = item.imgObj.width
canvasObj.height = item.imgObj.height
let ctx = canvasObj.getContext('2d')
let imageData = new ImageData(imgData, canvasObj.width, canvasObj.height)
ctx.putImageData(imageData, 0, 0)

        经测,常见的水印可以正常去除;对于不透明的水印,这里采用的是使用附近的图片色值来替代;假设原始图片本身也是半透明,这种情况下,透明度好计算,但色值计算存在些许误差,不过好在这种情况在现实中相对较少。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: 您可以使用以下Python代码来去除小红书上的图片水印:from PIL import Image import numpy as np#打开图片 im = Image.open('imagename.jpg')#转换为RGB格式 im = im.convert('RGB')#将图像转换为数组 im_array = np.array(im)#获取水印颜色 watermark_color = im_array[0, 0]#遍历数组,将水印颜色像素替换为白色 for i in range(im_array.shape[0]): for j in range(im_array.shape[1]): if im_array[i, j][0] == watermark_color[0] and im_array[i, j][1] == watermark_color[1] and im_array[i, j][2] == watermark_color[2]: im_array[i, j] = [255, 255, 255]#将数组转换为图像 im = Image.fromarray(im_array)#保存图像 im.save('imagename_watermark_removed.jpg') ### 回答2: 写一个小红书图片去水印的程序代码比较复杂,因为小红书的水印是嵌入在图片中的,需要通过图像处理的方法来去除。 首先,我们需要使用图像处理库,如OpenCV来读取图片。代码示例如下: ```python import cv2 def remove_watermark(image_path): # 读取图片 img = cv2.imread(image_path) # 定义水印的位置和大小 watermark_x = 100 # 水印的横坐标 watermark_y = 100 # 水印的纵坐标 watermark_width = 100 # 水印的宽度 watermark_height = 50 # 水印的高度 # 将水印位置的像素值设为背景色(例如白色) img[watermark_y : watermark_y + watermark_height, watermark_x : watermark_x + watermark_width] = [255, 255, 255] # 保存去水印后的图片 cv2.imwrite('no_watermark_image.jpg', img) # 使用示例 remove_watermark('watermarked_image.jpg') ``` 以上代码演示了一个简单的去除水印的过程,通过将水印位置的像素值设为背景色来实现。在实际应用中,可能需要根据具体的水印样式和位置,采用更复杂的图像处理算法来去除水印。 ### 回答3: 编写一个小红书图片去水印的程序代码需要使用图像处理的相关技术。以下是一个示例的程序代码: ```python import cv2 def remove_watermark(image_path, watermark_path, output_path): # 读取原始图片和水印图片 image = cv2.imread(image_path) watermark = cv2.imread(watermark_path) # 获取水印图片的宽高 w, h = watermark.shape[:2] # 在原始图片上定位水印位置 result = cv2.matchTemplate(image, watermark, cv2.TM_CCOEFF_NORMED) _, _, _, max_loc = cv2.minMaxLoc(result) top_left = max_loc bottom_right = (top_left[0] + w, top_left[1] + h) # 从原始图片中去除水印 image[top_left[1]:bottom_right[1], top_left[0]:bottom_right[0]] = 255 # 保存处理后的图片 cv2.imwrite(output_path, image) # 调用示例 remove_watermark("原始图片路径", "水印图片路径", "输出图片路径") ``` 上述代码使用OpenCV库来实现图像处理操作。首先,我们使用`cv2.imread`函数读取原始图片和水印图片。然后,我们使用`cv2.matchTemplate`函数在原始图片上进行模板匹配,查找水印位置。接下来,根据匹配结果,利用切片操作在原始图片上覆盖水印区域为白色。最后,使用`cv2.imwrite`函数保存处理后的图片。 请注意,由于不同的水印可能有不同的位置、大小和透明度等特征,上述代码仅提供了一种基本的去水印方法,可能无法适用于所有情况。在实际应用中,可能需要根据具体情况做进一步的调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

半吊子伯爵

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

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

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

打赏作者

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

抵扣说明:

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

余额充值