鱼C论坛

 找回密码
 立即注册
查看: 6330|回复: 39

[已解决]请问怎样按色差抠图

[复制链接]
发表于 2022-8-19 22:53:25 | 显示全部楼层 |阅读模式
50鱼币
本帖最后由 wgij007 于 2022-9-15 08:16 编辑




如上图,把与背景不一样的所有图块,以正方形抠出来(以长边为边长),抠出来图块与边上保留像素(也就是不靠在图片的边上),另存多张图片。可以批量处理多张图片(都是一样底色,里有多个图块)。底色那个值最好有一个范围可设。
感激帮忙。
最佳答案
2022-8-19 22:53:26
确实不好整
  1. #!/usr/bin/env python
  2. #coding=utf-8

  3. from PIL import Image
  4. import numpy as np
  5. import sys

  6. bg_color = (0, 0, 0xfe)

  7. def max(a, b): return a if a > b else b
  8. def min(a, b): return a if a < b else b

  9. def is_background(pic, y, x, tolerance = 0x30):
  10.     color = pic.getpixel((x, y))
  11.     for i in range(3):
  12.         if bg_color[i] + tolerance < color[i]: return False
  13.         if bg_color[i] - tolerance > color[i]: return False
  14.     return True

  15. def is_contain(location, y, x):
  16.     for i in location:
  17.         if (i[0] <= x <= i[2]) and (i[1] <= y <= i[3]): return True
  18.     return False

  19. def find_block_sub(y, x, buff):
  20.     if is_background(pic, y, x): return None
  21.     if buff[y][x]: return None
  22.     result = [x, y, x, y]
  23.     buff[y][x] = 1
  24.     for i in [[0, -1], [-1, 0], [0, 1], [1, 0]]:
  25.         temp = find_block_sub(y + i[0], x + i[1], buff)
  26.         if temp:
  27.             result[0] = min(result[0], temp[0])
  28.             result[1] = min(result[1], temp[1])
  29.             result[2] = max(result[2], temp[2])
  30.             result[3] = max(result[3], temp[3])
  31.     #buff[y][x] = 0     # 我感觉不复位,对这个程序也问题不大
  32.     return result

  33. def find_block(y, x): return find_block_sub(y, x, np.zeros((height, width)))

  34. def format(location, margin = 5):
  35.     for i in location:
  36.         i[0] -= margin
  37.         i[1] -= margin
  38.         i[2] += margin
  39.         i[3] += margin
  40.         width = i[2] - i[0]
  41.         height = i[3] - i[1]
  42.         distance = abs(width - height) / 2
  43.         if width == height: continue
  44.         if width > height:
  45.             i[1] -= distance
  46.             i[3] += distance
  47.         else:
  48.             i[0] -= distance
  49.             i[2] += distance

  50. sys.setrecursionlimit(10000)
  51. location = []
  52. pic = Image.open("pic.jpg")
  53. width, height = pic.size
  54. for y in range(height):
  55.     for x in range(width):
  56.         if not is_background(pic, y, x):
  57.             if not is_contain(location, y, x):
  58.                 location.append(find_block(y, x))

  59. format(location)
  60. for i in range(len(location)):
  61.     pic.crop(location[i]).save(str(i) + ".png")
复制代码

最佳答案

查看完整内容

确实不好整
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-19 22:53:26 | 显示全部楼层    本楼为最佳答案   
确实不好整
  1. #!/usr/bin/env python
  2. #coding=utf-8

  3. from PIL import Image
  4. import numpy as np
  5. import sys

  6. bg_color = (0, 0, 0xfe)

  7. def max(a, b): return a if a > b else b
  8. def min(a, b): return a if a < b else b

  9. def is_background(pic, y, x, tolerance = 0x30):
  10.     color = pic.getpixel((x, y))
  11.     for i in range(3):
  12.         if bg_color[i] + tolerance < color[i]: return False
  13.         if bg_color[i] - tolerance > color[i]: return False
  14.     return True

  15. def is_contain(location, y, x):
  16.     for i in location:
  17.         if (i[0] <= x <= i[2]) and (i[1] <= y <= i[3]): return True
  18.     return False

  19. def find_block_sub(y, x, buff):
  20.     if is_background(pic, y, x): return None
  21.     if buff[y][x]: return None
  22.     result = [x, y, x, y]
  23.     buff[y][x] = 1
  24.     for i in [[0, -1], [-1, 0], [0, 1], [1, 0]]:
  25.         temp = find_block_sub(y + i[0], x + i[1], buff)
  26.         if temp:
  27.             result[0] = min(result[0], temp[0])
  28.             result[1] = min(result[1], temp[1])
  29.             result[2] = max(result[2], temp[2])
  30.             result[3] = max(result[3], temp[3])
  31.     #buff[y][x] = 0     # 我感觉不复位,对这个程序也问题不大
  32.     return result

  33. def find_block(y, x): return find_block_sub(y, x, np.zeros((height, width)))

  34. def format(location, margin = 5):
  35.     for i in location:
  36.         i[0] -= margin
  37.         i[1] -= margin
  38.         i[2] += margin
  39.         i[3] += margin
  40.         width = i[2] - i[0]
  41.         height = i[3] - i[1]
  42.         distance = abs(width - height) / 2
  43.         if width == height: continue
  44.         if width > height:
  45.             i[1] -= distance
  46.             i[3] += distance
  47.         else:
  48.             i[0] -= distance
  49.             i[2] += distance

  50. sys.setrecursionlimit(10000)
  51. location = []
  52. pic = Image.open("pic.jpg")
  53. width, height = pic.size
  54. for y in range(height):
  55.     for x in range(width):
  56.         if not is_background(pic, y, x):
  57.             if not is_contain(location, y, x):
  58.                 location.append(find_block(y, x))

  59. format(location)
  60. for i in range(len(location)):
  61.     pic.crop(location[i]).save(str(i) + ".png")
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-23 08:15:28 | 显示全部楼层
顶一下,有点难
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-23 21:02:33 | 显示全部楼层
用爬虫,让网站抠完后用爬虫下载下来
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-24 22:48:54 | 显示全部楼层

老大,了不起呀!请问怎样可以做成批量呀,一个文件夹都是这种图,全部要抠出来。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-24 22:59:01 | 显示全部楼层
wgij007 发表于 2022-8-24 22:48
老大,了不起呀!请问怎样可以做成批量呀,一个文件夹都是这种图,全部要抠出来。

你能看懂我写的这个代码吗?
代码都给你了,稍微改一改就是你需要的了
这个程序完成了一张图片的处理,你需要做的就是遍历目录下面的图片,然后调用这个程序
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-25 00:36:15 | 显示全部楼层
人造人 发表于 2022-8-24 22:59
你能看懂我写的这个代码吗?
代码都给你了,稍微改一改就是你需要的了
这个程序完成了一张图片的处理, ...

刚学,不会呀
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-25 08:14:27 | 显示全部楼层
人造人 发表于 2022-8-24 22:59
你能看懂我写的这个代码吗?
代码都给你了,稍微改一改就是你需要的了
这个程序完成了一张图片的处理, ...

你好,背景色有一点色差,怎样设呀。如230~254
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-25 09:32:59 | 显示全部楼层
wgij007 发表于 2022-8-25 08:14
你好,背景色有一点色差,怎样设呀。如230~254

这不,只要偏差不超过0x30就认为是背景色

  1. def is_background(pic, y, x, tolerance = 0x30):
  2.     color = pic.getpixel((x, y))
  3.     for i in range(3):
  4.         if bg_color[i] + tolerance < color[i]: return False
  5.         if bg_color[i] - tolerance > color[i]: return False
  6.     return True
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-25 10:05:22 | 显示全部楼层
  1. #!/usr/bin/env python
  2. #coding=utf-8

  3. from PIL import Image
  4. import numpy as np
  5. import sys
  6. from glob import glob
  7. import os
  8. import shutil

  9. bg_color = (0, 0, 0xfe)

  10. def max(a, b): return a if a > b else b
  11. def min(a, b): return a if a < b else b

  12. def is_background(pic, y, x, tolerance = 0x30):
  13.     color = pic.getpixel((x, y))
  14.     for i in range(3):
  15.         if bg_color[i] + tolerance < color[i]: return False
  16.         if bg_color[i] - tolerance > color[i]: return False
  17.     return True

  18. def is_contain(location, y, x):
  19.     for i in location:
  20.         if (i[0] <= x <= i[2]) and (i[1] <= y <= i[3]): return True
  21.     return False

  22. def find_block_sub(pic, y, x, buff):
  23.     if is_background(pic, y, x): return None
  24.     if buff[y][x]: return None
  25.     result = [x, y, x, y]
  26.     buff[y][x] = 1
  27.     for i in [[0, -1], [-1, 0], [0, 1], [1, 0]]:
  28.         temp = find_block_sub(pic, y + i[0], x + i[1], buff)
  29.         if temp:
  30.             result[0] = min(result[0], temp[0])
  31.             result[1] = min(result[1], temp[1])
  32.             result[2] = max(result[2], temp[2])
  33.             result[3] = max(result[3], temp[3])
  34.     #buff[y][x] = 0     # 我感觉不复位,对这个程序也问题不大
  35.     return result

  36. def find_block(pic, y, x, size): return find_block_sub(pic, y, x, np.zeros(size))

  37. def format(location, margin = 5):
  38.     for i in location:
  39.         i[0] -= margin
  40.         i[1] -= margin
  41.         i[2] += margin
  42.         i[3] += margin
  43.         width = i[2] - i[0]
  44.         height = i[3] - i[1]
  45.         distance = abs(width - height) / 2
  46.         if width == height: continue
  47.         if width > height:
  48.             i[1] -= distance
  49.             i[3] += distance
  50.         else:
  51.             i[0] -= distance
  52.             i[2] += distance

  53. def generate_pic(result_path, filename):
  54.     location = []
  55.     pic = Image.open(filename)
  56.     width, height = pic.size
  57.     for y in range(height):
  58.         for x in range(width):
  59.             if not is_background(pic, y, x):
  60.                 if not is_contain(location, y, x):
  61.                     location.append(find_block(pic, y, x, (height, width)))

  62.     format(location)
  63.     for i in range(len(location)):
  64.         pic.crop(location[i]).save(result_path + "/" + str(i) + ".jpg")

  65. sys.setrecursionlimit(10000)
  66. for i in glob("pic/*.jpg"):
  67.     filename = os.path.splitext(os.path.split(i)[-1])[0]
  68.     shutil.rmtree("result/" + filename)
  69.     os.mkdir("result/" + filename)
  70.     generate_pic("result/" + filename, i)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-26 08:04:28 | 显示全部楼层

老大,这输入路径在那了,没找到呀
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-26 08:13:06 | 显示全部楼层

请问能不能直接读取某一个像素的值呢,如,10,10 这样
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-26 09:09:24 | 显示全部楼层
wgij007 发表于 2022-8-26 08:04
老大,这输入路径在那了,没找到呀
  1. for i in glob("pic/*.jpg"):
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-26 09:09:54 | 显示全部楼层
wgij007 发表于 2022-8-26 08:13
请问能不能直接读取某一个像素的值呢,如,10,10 这样
  1. color = pic.getpixel((x, y))
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-26 18:50:23 | 显示全部楼层

for i in glob("d:/aaa/1/*.jpg"): 一改就出错了

Traceback (most recent call last):
  File "抠图.py", line 81, in <module>
    shutil.rmtree("result/" + filename)
  File "D:\Program Files\Python37\lib\shutil.py", line 516, in rmtree
    return _rmtree_unsafe(path, onerror)
  File "D:\Program Files\Python37\lib\shutil.py", line 377, in _rmtree_unsafe
    onerror(os.scandir, path, sys.exc_info())
  File "D:\Program Files\Python37\lib\shutil.py", line 374, in _rmtree_unsafe
    with os.scandir(path) as scandir_it:
FileNotFoundError: [WinError 3] 系统找不到指定的路径。: 'result/001'
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-26 20:02:34 | 显示全部楼层
wgij007 发表于 2022-8-26 18:50
for i in glob("d:/aaa/1/*.jpg"): 一改就出错了

Traceback (most recent call last):

我把结果存在result这个目录
我没有用代码创建这个目录,你自己创建一下
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-26 21:55:41 | 显示全部楼层
人造人 发表于 2022-8-26 20:02
我把结果存在result这个目录
我没有用代码创建这个目录,你自己创建一下

好的,还是不慬,但非常感谢你。我自己摸索一下先。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-26 22:46:05 | 显示全部楼层
人造人 发表于 2022-8-26 20:02
我把结果存在result这个目录
我没有用代码创建这个目录,你自己创建一下

001.png

在pic里没有图片,就不报错,有图片就报错。result文件夹已创建了。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-8-26 23:04:30 | 显示全部楼层
wgij007 发表于 2022-8-26 22:46
在pic里没有图片,就不报错,有图片就报错。result文件夹已创建了。

报错信息?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2022-8-26 23:34:29 | 显示全部楼层

002.png 这个PIC文件夹里有图片的。
003.png   这个没有图片,空的
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-26 19:23

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表