Python 3.5(主要和输出)(当前处于非竞争状态)
生日快乐,挑战!这是您的礼物:答案!
编辑:将输出转换为python代码,改善了压缩率(略)编辑2:在size
为1 时将其打印为原始图像。改进了分数,但需要再次计算分数。EDIT3:@Dennis指出我仍然有要修复的错误,因此我将答案标记为不竞争
码:
import sys
LIST = [' ','`','.',',',':',';',"'",'+','#','@']
def charxel_to_brightness(charxel):
return LIST.index(charxel)
def brightness_to_charxel(bright):
return LIST[bright]
def image_to_brightness(imagetext):
return [list(map(charxel_to_brightness,line)) for line in imagetext.split("\n")]
def brightness_to_image(brightarray):
return '\n'.join([''.join(map(brightness_to_charxel,line)) for line in brightarray])
def split_into_parts(lst,size):
return [lst[x:x+size] for x in range(0, len(lst), size)]
def gen_updown(startxel,endxel,size):
return [[int((size-r)*(endxel-startxel)/size+startxel) for c in range(size)] for r in range(size)]
def gen_leftright(startxel,endxel,size):
return [[int((size-c)*(endxel-startxel)/size+startxel) for c in range(size)] for r in range(size)]
def gen_tlbr(startxel,endxel,size):
return [[int((2*size-r-c)/2*(endxel-startxel)/size+startxel) for c in range(size)] for r in range(size)]
def gen_bltr(startxel,endxel,size):
return [[int((size-r+c)/2*(endxel-startxel)/size+startxel) for c in range(size)] for r in range(size)]
def gen_block(code,startxel,endxel,size):
if code==0:return gen_updown(startxel,endxel,size)
if code==1:return gen_leftright(startxel,endxel,size)
if code==2:return gen_bltr(startxel,endxel,size)
if code==3:return gen_tlbr(startxel,endxel,size)
def vars_to_data(code,startxel,endxel):
acc=endxel
acc+=startxel<<4
acc+=code<<8
return acc
def data_to_vars(data):
code=data>>8
startxel=(data>>4)&15
endxel=data&15
return code,startxel,endxel
def split_into_squares(imgarray,size):
rows = split_into_parts(imgarray,size)
allsquares = []
for rowblock in rows:
splitrows = []
for row in rowblock:
row = split_into_parts(row,size)
splitrows.append(row)
rowdict = []
for row in splitrows:
for x in range(len(row)):
if len(rowdict)<=x:
rowdict.append([])
rowdict[x].append(row[x])
allsquares.append(rowdict)
return allsquares
def calc_quality(imgarray,comparray):
acc=0
for row in range(len(imgarray)):
for col in range(len(imgarray[row])):
acc+=pow(imgarray[row][col]-comparray[row][col],2)
return (1-(acc/81.0/sum([len(row) for row in imgarray]))**.5)**8
def fuse_squares(squarray):
output=[]
counter=0
scounter=0
sqrow=0
while sqrow<len(squarray):
if scounter<len(squarray[sqrow][0]):
output.append([])
for square in squarray[sqrow]:
output[counter].extend(square[scounter])
scounter+=1
counter+=1
else:
scounter=0
sqrow+=1
return output
def main_calc(imgarray,threshold):
imgarray = image_to_brightness(imgarray)
size = 9
quality = 0
compimg=[]
datarray=[]
testdata = [vars_to_data(c,s,e) for c in range(4) for s in range(10) for e in range(10)]
while quality<threshold:
squares = split_into_squares(imgarray,size)
compimg = []
datarray = []
testblock = [gen_block(c,s,e,size) for c in range(4) for s in range(10) for e in range(10)]
for row in squares:
comprow = []
datrow=[]
for square in row:
quality_values = [calc_quality(square,block) for block in testblock]
best_quality = quality_values.index(max(quality_values))
comprow.append(testblock[best_quality])
datrow.append(testdata[best_quality])
compimg.append(comprow)
datarray.append(datrow)
compimg = fuse_squares(compimg)
quality = calc_quality(imgarray,compimg)
print("Size:{} Quality:{}".format(size,quality))
size-=1
return brightness_to_image(compimg),datarray,size+1
template = '''def s(d,s,e,z):
x=range(z)
return d<1 and[[int((z-r)*(e-s)/z+s)for c in x]for r in x]or d==1 and[[int((z-c)*(e-s)/z+s)for c in x]for r in x]or d==2 and[[int((2*z-r-c)/2*(e-s)/z+s)for c in x]for r in x]or d>2 and[[int((z-r+c)/2*(e-s)/z+s)for c in x] for r in x]
i=lambda a:'\\n'.join([''.join(map(lambda r:" `.,:;'+#@"[r],l))for l in a])
def f(a):
o=[];c=0;s=0;r=0
while r<len(a):
if s<len(a[r][0]):
o.append([])
for q in a[r]:
o[c].extend(q[s])
s+=1;c+=1
else:
s=0;r+=1
return o
t={};z={}
print(i(f([[s(D>>8,(D>>4)&15,D&15,z)for D in R]for R in t])))'''
template_size_1 = '''print("""{}""")'''
def main(filename,threshold):
print(filename+" "+str(threshold))
file = open(filename,'r')
compimg,datarray,size = main_calc(file.read(),threshold)
file.close()
textoutput = open(filename.split(".")[0]+"-"+str(threshold*100)+".txt",'w')
textoutput.write(compimg)
textoutput.close()
compoutput = open(filename.split(".")[0]+"-"+str(threshold*100)+".py",'w')
datarray = str(datarray).replace(" ","")
code = ""
if size==1:
code = template_size_1.format(compimg)
else:
code= template.format(datarray,str(size))
compoutput.write(code)
compoutput.close()
print("done")
if __name__ == "__main__":
main(sys.argv[1],float(sys.argv[2]))
这个答案可以使用 进行很多改进,因此我可能会在周末进行更多的工作。
工作原理:
- 将图像分成大小块
size
。
- 查找最佳匹配块
- 计算整个图像的质量(根据公式)。
- 如果正确,则将压缩图像写入文件。
- 否则,请递减并重
size
试。
该算法适用于低质量(0.5、0.6),但不适用于较高质量的图像(实际上是膨胀的)。这也真的很慢。
这里有所有生成的文件,因此您无需再次重新生成它们。