See the Pen yLOQNKZ by Cartelet Cydius (@cartelet-cydius) on CodePen.
Mr. Uzura Info selbst Es gab einen Tweet auf Twitter, in dem er gebeten wurde, die Animationsliste nicht im Format von Mr. Uzura Info zu veröffentlichen. Mit Ausnahme eines Beispiels vom Anfang dieses Artikels sollte die Animationsliste danach veröffentlicht werden Ist das Original? Ich würde es gerne aus dem Design von machen (obwohl ich es erhalten habe). Wenn Sie ein Bild im Uzura-Info-Stil wünschen, führen Sie das veröffentlichte Programm aus.
Sie können es von hier aus auf Colab generieren. [Beispiel für ein Skript zur automatischen Generierung von Animationslisten](https://colab.research.google.com/github/Cartelet0423/animeListGen/blob/master/%E4%BE%8B%E3%81%AE%E3%82%A2 % E3% 83% 8B% E3% 83% A1% E3% 83% AA% E3% 82% B9% E3% 83% 88% E8% 87% AA% E5% 8B% 95% E7% 94% 9F% E6 % 88% 90% E3% 82% B9% E3% 82% AF% E3% 83% AA% E3% 83% 97% E3% 83% 88.ipynb)
Kennen Sie Uzurainfo? Wenn Sie Anime mögen, wurden Sie vielleicht einmal betreut, ohne den Namen zu kennen. Von ungefähr 2011 bis jetzt hat er eine Anime-Liste wie $ ↓ $ jede coole gemacht.
Herr Uzura Info scheint die Produktion der Animationsliste in diesem Semester (Sommeranimation 2020) abzuschließen. → Mitteilung über die Einstellung der Listenerstellung Vielen Dank für das, was Sie getan haben.
Es gibt jedoch eine große Liste, die auf einen Blick zu sehen ist, und viele Menschen, einschließlich mir, halten dies für notwendig.
** Ich habe ein Programm geschrieben, das solche Bilder ohne Erlaubnis erstellt. **
Da ich das Programm nur ausführen muss, möchte ich es in jedem Zeitraum aktualisieren, es sei denn, ich vergesse es oder die Quelle animateTimes beendet die Aktualisierung der Liste. (Updates finden Sie oben auf der Seite).
Erklärendes Bild oben links Alles andere wird innerhalb des Programms hergestellt. (Dieses Bild kann auch im Programm erstellt werden, aber da das Anpassen der Position der Zeichen schwierig ist, habe ich es mit einer Fotoshow gemacht.)
・ Basisbildmaterial generieren
· Informationen von ** animateTimes ** erhalten ・ Formatieren Sie die Informationen in den Wörterbuchtyp ・ Trennen Sie Sätze, die in einer Zeile zu lang sind, und fügen Sie Zeilenumbrüche ein, damit sie nicht an seltsamen Positionen unterbrochen werden.
lbpcascade_animeface.xml
ist erforderlich)
Referenz: Anime-Gesichtserkennung mit OpenCVEs kann schwierig zu lesen sein, da es sich nur um eine in Jupyter geschriebene Funktion handelt 9/23 Verbesserte Zeicheneinfügung
from requests import get
import re
from bs4 import BeautifulSoup
from math import ceil
from janome.tokenizer import Tokenizer
from PIL import Image, ImageFont, ImageDraw, ImageFilter
import matplotlib.pyplot as plt
from io import BytesIO
import unicodedata
import numpy as np
import cv2
classifier = cv2.CascadeClassifier('lbpcascade_animeface.xml')
t = Tokenizer()
template = Image.new('RGB', (158, 332), (71, 71, 71))
part = Image.fromarray(np.r_[[[np.linspace(130.5, 84.5, 256)] * 256] *
3].T.astype(np.uint8))
aimsize = {
"Titel": (157, 39),
"Produktionsunternehmer": (70, 39),
"Mitarbeiter": (86, 99),
"Besetzung": (70, 112),
"Sendeplan": (86, 52),
"Original": (157, 37),
}
aimpoint = {
"Titel": (0, 103),
"Produktionsunternehmer": (0, 142),
"Mitarbeiter": (71, 195),
"Besetzung": (0, 182),
"Sendeplan": (71, 142),
"Original": (0, 295),
}
def get_data(url):
global Title
html = get(url).text
soup = BeautifulSoup(html, 'html.parser')
for i in soup.select("br"):
i.replace_with("\n")
Title = re.sub("(\d+)(.+)", "\\1\n\\2",
soup.title.text.replace("|", "|").split("|")[0])
#"
li = []
headingh2 = soup.find_all('h2', class_='c-heading-h2')
if headingh2[0].get("id") != "1":
headingh2.pop(0)
for i, j in zip(headingh2, soup.find_all('table')):
a = [k.text for k in j.select("th")]
a.append(a[0])
a[0] = i.text
aa = []
for e in i.next_elements:
if e.name == "img":
aa.append(e["src"])
break
for k in a:
if k:
if k[0] == "\n":
k = k[1:]
aa.append(k)
li.append(aa)
data = {}
for i in li:
d = {"img": "", "Original": "", "Besetzung": "", "Produktionsunternehmer": "", "Sendeplan": ""}
data[i[1]] = d
d["img"] = i[0]
d["Sendeplan"] = i[-1]
d["Besetzung"] = "\n".join(re.findall(".+:(.+)", i[2].replace(":", ":")))
staff = []
for j in i[3].splitlines():
j = j.replace(":", ":")
if len(j.split(':')) < 2: continue
if "Original" in j:
d["Original"] = " ".join(j.split(':')[1:])
elif "Produktion" in j:
d["Produktionsunternehmer"] = j.split(':')[1]
else:
staff.append("\n".join(j.split(':')))
d["Mitarbeiter"] = "\n".join(staff)
for j in soup.find(text=f"『{i[1]}] Neuester Artikel / verwandte Videoliste").previous_elements:
if j.name == "a" and "Seite? ˅" in j.text:
data[i[1]]['href'] = j["href"]
break
return data
def len_(text):
count = 0
for c in text:
if unicodedata.east_asian_width(c) in 'FWA':
count += 2
else:
count += 1
return count
def nn(text, w):
tt = ""
l = 0
for j in t.tokenize(text, wakati=True):
if l + len(j) > w:
tt += "\n"
l = 0
elif j == "\n":
l = 0
tt += j
l += len(j)
return tt.replace("\n\n", "\n")
def mojiire(text, font_path, tmp, aimsize, aimpoint, case, hopt):
text = text.replace("\n ", "\n")
if case == 1:
tm = Image.new('RGB', (256, 256), (66, 58, 59))
if text:
text = nn(text, 14)
elif case == 2:
tm = part.copy()
if text:
text = nn("\n".join(text.splitlines()[-3:]), 10) + "\n "
elif case == 3:
tm = part.copy()
if text:
text = nn(text, 20)
while len_(text) < 20:
text += " "
else:
tm = part.copy()
if text:
text = nn("\n".join(text.splitlines()[:8]), 10)
if text:
while len(text.splitlines()) < hopt:
text += "\n "
font = ImageFont.truetype(font_path, 100)
draw = ImageDraw.Draw(tm)
x, y = draw.textsize(text, font=font, spacing=1)
tm = tm.resize((x + 30, y + 30))
draw = ImageDraw.Draw(tm)
draw.text((15, 15), text, font=font, spacing=1)
tm = tm.resize(aimsize)
if case == 2:
draw = ImageDraw.Draw(tm)
draw.line((0, 39, aimsize[0], 39), fill=(179, 179, 179), width=1)
else:
tm = tm.resize(aimsize)
tmp.paste(tm, aimpoint)
def main(url, font_title, font_main):
data = get_data(url)
titles = list(data.keys())
inList = True
for x in range(ceil((len(titles) + 1) / 6)):
for y in range(6):
i = x * 6 + y - 1
tmp = template.copy()
if i == -1:
tmp = Image.open("Pfad des Erklärungsbildes oben links").convert("RGB")
font = ImageFont.truetype(font_main, 20)
draw = ImageDraw.Draw(tmp)
draw.text((2, 2), Title, (96, 167, 200), font=font, spacing=1)
tmp = np.array(tmp)
elif i < len(titles):
for kw in aimsize.keys():
if kw == "Titel":
case = 1
hopt = 1
elif kw == "Sendeplan":
case = 2
hopt = 3
elif kw == "Original":
case = 3
hopt = 2
else:
case = 0
if kw == "Produktionsunternehmer":
hopt = 2
else:
hopt = 6
mojiire(titles[i] if kw == "Titel" else data[titles[i]][kw],
font_title if kw == "Titel" else font_main, tmp,
aimsize[kw], aimpoint[kw], case, hopt)
try:
img = Image.open(
BytesIO(get(
data[titles[i]]["img"]).content)).convert("RGB")
gray_image = cv2.cvtColor(np.array(img),
cv2.COLOR_BGR2GRAY)
faces = classifier.detectMultiScale(gray_image)
h, w = img.height, img.width
if len(faces):
x_, y_ = (
np.r_[[faces[:, 3]**2 /
(faces[:, 3]**2).sum()]].T *
(faces[:, :2] + faces[:, 2:] * .5)).sum(axis=0,
dtype=int)
else:
x_, y_ = 0.5 * w, 0.45 * h
if w > 1.5 * h:
cropped_image = img.crop(
(max(0, int(x_ - .75 * h)) -
max(0,
int(x_ + .75 * h) - w), 0,
min(w, int(x_ + .75 * h)) +
max(0, -int(x_ - .75 * h)), h))
else:
cropped_image = img.crop(
(0, max(0, int(y_ - (1 / 3) * w)) -
max(0,
int(y_ + (1 / 3) * w) - h), w,
min(h, int(y_ + (1 / 3) * w)) +
max(0, -int(y_ - (1 / 3) * w))))
tmp = np.array(tmp)
tmp[:103, :-1] = np.array(cropped_image.resize((157, 103)))
except Exception as e:
print(e)
elif inList:
foundation = np.array(template)
foundation[20:, :10] = 0
foundation[:2] = 0
tmp = np.array(
Image.fromarray(foundation).filter(
ImageFilter.GaussianBlur(10.0)))
inList = False
else:
foundation = np.array(template)
foundation[:2] = 0
tmp = np.array(
Image.fromarray(foundation).filter(
ImageFilter.GaussianBlur(10.0)))
try:
line = np.r_["1", line, tmp]
except:
line = tmp.copy()
try:
image = np.r_["0", image, line]
except:
image = line.copy()
del line
plt.imsave(f"{''.join(Title.splitlines())}.png ", image)
if __name__ == "__main__":
url = "https://www.animatetimes.com/tag/details.php?id=5947" #URL von animateTimes
font_title = "C:\\Windows\\Fonts\\YuGothB.ttc" #Schriftpfad für den Titelteil
font_main = "C:\\Windows\\Fonts\\YuGothM.ttc" #Pfade anderer Schriftarten
main(url, font_title, font_main)
・ Schwäche gegenüber Änderungen in der Struktur der Informationsquellen-Site ・ Wenn es nicht als Gesicht erkannt wird oder wenn die Komposition verstreute Gesichter hat, kann das Schneiden miserabel sein.
Die Details sind alles andere als handgemacht, aber ich denke, dass die notwendigen Informationen als Mindestliste unterdrückt wurden.
Recommended Posts