上升还是下降?


309

给定山羊的图像,您的程序应该最好尝试识别山羊是否倒置。

例子

这些是输入可能是什么的示例。不是实际的投入

输入:

下山羊

输出: Downgoat

规格

您的程序最多应为30,000个字节

  • 输入将包含完整的山羊
  • 图片将始终包含山羊
  • 如果山羊倒立,输出Downgoat,否则Upgoat

输入将是您可以将图像作为输入(文件名,图像的base64等)。

要点文件名仅供参考,不要依赖于包含“ Upgoat”或“ Downgoat”的图像名称或其他元数据。


请不要硬编码。这很无聊,我无法完全执行它,但是我可以很好地询问。

测试用例

要点与图像。开头的图像downgoat具有Downgoat输出和图像开始与upgoatUpgoat输出。

第二批测试用例 确保在所有测试用例上测试图像。这些图像是jpgs。图像大小确实有所不同,但没有太多。


注意:在接受答案之前,可以添加一些测试用例,以避免使用硬编码的答案并检查程序的总体性能。

正确获得我的头像的奖励积分:P

计分

分数是可以通过以下方式计算的百分比: (number_correct / total) * 100


1
“拟合”是否算作硬编码?
尼克T

@NickT“拟合”是什么意思?
Downgoat

@Downgoat模型(方程式)的上升参数,如果山羊朝向正确的方向则输出该参数。通过“ ‘装修’ ”我的意思是拟合模型的整个数据集,对一些训练集。
尼克T


29
我很好奇,看看这些解决方案将如何在一幅图中处理两只山羊。
丹尼尔(Daniel)

Answers:


293

Mathematica,100%,141个字节

f@x_:=Count[1>0]@Table[ImageInstanceQ[x,"caprine animal",RecognitionThreshold->i/100],{i,0,50}];If[f@#>f@ImageReflect@#,"Up","Down"]<>"goat"&

好吧,这感觉有点像作弊。它也非常慢而且非常愚蠢。通过功能f可以大致看出您可以在Mathematica的计算机视觉内置模块之一中设置识别阈值的高度,并且仍然可以将图像识别为山羊动物。

然后,我们查看图像或翻转后的图像是否更像山羊皮。仅在领带被打断而朝下走时才可在您的个人资料图片上使用。可能有很多方法可以改进此方法,包括询问图像是否代表Bovids或Caprine动物实体类型的其他概括。

第一个测试集的笔试成绩为100%,第二个测试集的笔试成绩为94%,因为该算法对山羊1产生不确定的结果。这可以提高到100%,而这需要更长的计算时间,测试更多的价值RecognitionThreshold。从100升至1000足够 由于某些原因,Mathematica认为这是非常不满意的图像!将识别实体从山羊动物转变为有蹄哺乳动物似乎也可行。

取消高尔夫:

goatness[image_] := Count[
                      Table[
                        ImageInstanceQ[
                          image, Entity["Concept", "CaprineAnimal::4p79r"],
                          RecognitionThreshold -> threshold
                        ],
                        {threshold, 0, 0.5, 0.01}
                      ],
                      True
                    ]

Function[{image},
  StringJoin[      
    If[goatness[image] > goatness[ImageReflect[image]],
      "Up",
      "Down"
    ],
    "goat"
  ]
]

替代解决方案,100%+奖金

g[t_][i_] := ImageInstanceQ[i, "caprine animal", RecognitionThreshold -> t]
f[i_, l_: 0, u_: 1] := Module[{m = (2 l + u)/3, r},
  r = g[m] /@ {i, ImageReflect@i};
  If[Equal @@ r,
   If[First@r, f[i, m, u], f[i, l, m]],
   If[First@r, "Up", "Down"] <> "goat"
   ]
  ]

该算法使用与以前相同的策略,但是二进制搜索超出了阈值。这里涉及两个功能:

  • g[t]返回其参数是否为带有阈值的山羊图像t
  • f接受三个参数:一个图像,以及阈值的上限和下限。它是递归的;它通过测试m上限和下限(偏向下限)之间的阈值来工作。如果图像和反射图像都是山羊皮的或非山羊皮的,则会适当消除范围的下部或上部,然后再次调用自身。否则,如果一个图像是山羊皮的,而另一个图像是非山羊皮的,则Upgoat如果第一个图像是山羊皮的,则返回该图像(Downgoat否则,则返回)(如果第二个图像是山羊皮的,则返回)。

函数定义值得一点解释。首先,函数应用是左关联的。这意味着类似的东西g[x][y]被解释为(g[x])[y]; “ g[x]适用于y。”

其次,Mathematica中的分配大致等同于定义替换规则。也就是说,f[x_] := x^2并不意味着“声明一个以f参数名x返回的函数x^2;” 它的含义更接近于“当您看到类似的东西时f[ ... ],将其放入内部x并将其替换为x^2 ”。

将这两个放在一起,我们可以看到的定义g告诉Mathematica替换该形式的任何表达式(g[ ... ])[ ... ]赋值的右侧。

当Mathematica遇到表达式g[m](在的第二行f)时,它会看到该表达式不匹配它知道的任何规则,并且保持不变。然后,它匹配Map运算符/@,其参数是g[m]和列表{i, ImageReflect@i}。(/@是infix表示法;此表达式与Map[g[m], { ... }]。完全等效。)Map通过将其第一个参数应用于第二个参数的每个元素来替换,因此得到{(g[m])[i], (g[m])[ ... ]}。现在Mathematica看到每个元素都与g并进行替换。

这样,我们就g可以像一个函数一样操作,返回另一个函数。也就是说,它的行为大致就像我们写的那样:

g[t_] := Function[{i}, ImageInstanceQ[i, "caprine animal", RecognitionThreshold -> t]]

(除了在这种情况下g[t],它自己求值为a Function,而在此之前g[t],它本身并未进行任何转换。)

我使用的最后一个技巧是可选模式。该模式的l_ : 0意思是“匹配任何表达式并将其用作l,或不匹配任何表达式并将其0用作” l。因此,如果您f[i]使用一个参数(要测试的图像)进行调用,就好像您已经调用一样f[i, 0, 1]

这是我使用的测试工具:

gist = Import["https://api.github.com/gists/3fb94bfaa7364ccdd8e2", "JSON"];
{names, urls} = Transpose[{"filename", "raw_url"} /. Last /@ ("files" /. gist)];
images = Import /@ urls;
result = f /@ images
Tally@MapThread[StringContainsQ[##, IgnoreCase -> True] &, {names, result}]
(* {{True, 18}} *)

user = "items" /.
           Import["https://api.stackexchange.com/2.2/users/40695?site=codegolf", "JSON"];
pic = Import[First["profile_image" /. user]];
name = First["display_name" /. user];
name == f@pic
(* True *)

344
Mathematica具有用于确定山羊的内置函数。我不知道这感觉如何。
罗伯特·弗雷泽

119
Whaaat Oo内置了此功能 ....哇...
Downgoat

171
您是在开玩笑吗...
corsiKa '16

27
+1可使Mathematica看到哪个图像更“山羊皮”。
QBrute

9
这是非常荒谬的。+1。
ApproachingDarknessFish

71

JavaScript,93.9%

var solution = function(imageUrl, settings) {

  // Settings
  settings = settings || {};
  var colourDifferenceCutoff = settings.colourDifferenceCutoff || 0.1,
      startX = settings.startX || 55,
      startY = settings.startY || 53;

  // Draw the image to the canvas
  var canvas = document.createElement("canvas"),
      context = canvas.getContext("2d"),
      image = new Image();
  image.src = imageUrl;
  image.onload = function(e) {
    canvas.width = image.width;
    canvas.height = image.height;
    context.drawImage(image, 0, 0);

    // Gets the average colour of an area
    function getColour(x, y) {

      // Get the image data from the canvas
      var sizeX = image.width / 100,
          sizeY = image.height / 100,
          data = context.getImageData(
            x * sizeX | 0,
            y * sizeY | 0,
            sizeX | 0,
            sizeY | 0
          ).data;

      // Get the average of the pixel colours
      var average = [ 0, 0, 0 ],
          length = data.length / 4;
      for(var i = 0; i < length; i++) {
        average[0] += data[i * 4] / length;
        average[1] += data[i * 4 + 1] / length;
        average[2] += data[i * 4 + 2] / length;
      }
      return average;
    }

    // Gets the lightness of similar colours above or below the centre
    function getLightness(direction) {
      var centre = getColour(startX, startY),
          colours = [],
          increment = direction == "above" ? -1 : 1;
      for(var y = startY; y > 0 && y < 100; y += increment) {
        var colour = getColour(startX, y);

        // If the colour is sufficiently different
        if(
          (
            Math.abs(colour[0] - centre[0]) +
            Math.abs(colour[1] - centre[1]) +
            Math.abs(colour[2] - centre[2])
          ) / 256 / 3
          > colourDifferenceCutoff
        ) break;
        else colours.push(colour);
      }

      // Calculate the average lightness
      var lightness = 0;
      for(var i = 0; i < colours.length; i++) {
        lightness +=
          (colours[i][0] + colours[i][1] + colours[i][2])
          / 256 / 3 / colours.length;
      }

      /*
      console.log(
        "Direction:", direction,
        "Checked y = 50 to:", y,
        "Average lightness:", lightness
      );
      */
      return lightness;
    }

    // Compare the lightness above and below the starting point
    //console.log("Results for:", imageUrl);
    var above = getLightness("above"),
        below = getLightness("below"),
        result = above > below ? "Upgoat" : "Downgoat";
    console.log(result);
    return result;
  };
};
<div ondrop="event.preventDefault();r=new FileReader;r.onload=e=>{document.getElementById`G`.src=imageUrl=e.target.result;console.log=v=>document.getElementById`R`.textContent=v;solution(imageUrl);};r.readAsDataURL(event.dataTransfer.files[0]);" ondragover="event.preventDefault()" style="height:160px;border-radius:12px;border:2px dashed #999;font-family:Arial,sans-serif;padding:8px"><p style="font-style:italic;padding:0;margin:0">Drag & drop image <strong>file</strong> (not just link) to test here... (requires HTML5 browser)</p><image style="height:100px" id="G" /><pre id="R"></pre></div>

说明

@BlackCap的检查光从哪里来的想法的简单实现。

大多数山羊位于其图像的中心,并且由于阳光的照射,它们的腹部总是比它们的背部更黑。程序从图像的中间开始,并记下颜色。然后,它获取中心上方和下方的像素的平均亮度,直到颜色与中心颜色不同(山羊的主体终止且背景开始时)为止。哪一侧更轻便确定它是上升还是下降。

在第二个测试用例中,下行9和上行7和9失败。


4
真好!我没想到100%会这么容易。我添加了第二批测试用例,您可以基于此更新您的答案吗?
Downgoat


@Downgoat是的。分数已更新。
user81655 '02

不幸的是,在我将图像旋转180°并将其垂直翻转后,它失败了。萤幕撷取画面
mr5

@ mr5有趣的...那么屏幕快照中的图像与Downgoat 4略有不同吗?浏览器之间(也许还有操作系统之间)也存在细微差异。使用此答案中的参数,对于Chrome和Firefox(使用Windows),我都得到了相同的结果。
user81655 '16

63

Python,100%,225个字节

import requests

SEARCH = "http://www.bing.com/images/searchbyimage?FORM=IRSBIQ&cbir=sbi&imgurl="
THRESHOLD = 30
url = raw_input()
print "Upgoat" if requests.get(SEARCH + url).content.count('img') > THRESHOLD else "Downgoat"

对山羊使用反向图像搜索。如果页面返回的结果令人满意,则可能是山羊。如果手绘山羊或Bing遭到损坏,此解决方案可能无法使用。


32
我不确定这个答案如何。这是有效的边界,几乎违反了这个漏洞。当前,它违反了明确的规则,即输入是文件或本地路径,而不是URL。这是一个有趣的答案,但考虑到边界的有效性,我想说它的竞争力值得怀疑。
Downgoat

50
@Downgoat,所以您认为他的答案正确吗?
2016年

2
通过将文件上传到imgur或其他方式修复它^^另外,为什么在世界上仍会使用bing?
Eumel '02

17
@Eumel因为Google会检查HTTP请求中的User-Agent是否属于实际的Web浏览器(或它们允许的内容),而不属于某个其他应用程序或脚本。Bing不会检查,他们对于收到传入的请求有点拼命。我猜User-Agent可以伪装成额外的代码,并且没关系,因为这不是代码高尔夫。
JordiVilaplana'2

14
该标准漏洞可用来解决高尔夫球的代码问题,从而使答案更小。这不是高尔夫
编程的

58

爪哇,93.9% 100%

这通过确定图像上部和下部的行对比度来实现。我认为图像下半部分的对比度较大,原因有两个:

  • 4条腿在底部
  • 上部的背景会变得模糊,因为它通常是离焦区域

我通过计算相邻像素值的差,对差进行平方并加总所有平方来确定每一行的对比度。

更新资料

第二批中的某些图像导致原始算法出现问题。

upgoat3.jpg

该图像使用的透明度以前被忽略。解决此问题的方法有多种,但我只是选择在400x400黑色背景上渲染所有图像。这具有以下优点:

  • 使用Alpha通道处理图像
  • 处理索引和灰度图像
  • 提高性能(无需处理那些13MP图像)

downgoat8.jpg / upgoat8.jpg

这些图像放大了山羊体内的细节。解决方案是仅在垂直方向上模糊图像。但是,这产生了第一批图像的问题,这些图像在背景中具有垂直结构。解决方案是简单地计算超过一定阈值的差异,而忽略差异的实际值。

简而言之,经过更新的算法会查找图像中具有很多差异的区域,这些区域在预处理后如下所示:

在此处输入图片说明

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class UpDownGoat {
    private static final int IMAGE_SIZE = 400;
    private static final int BLUR_SIZE = 50;

    private static BufferedImage blur(BufferedImage image) {
        BufferedImage result = new BufferedImage(image.getWidth(), image.getHeight() - BLUR_SIZE + 1,
                BufferedImage.TYPE_INT_RGB);
        for (int b = 0; b < image.getRaster().getNumBands(); ++b) {
            for (int x = 0; x < result.getWidth(); ++x) {
                for (int y = 0; y < result.getHeight(); ++y) {
                    int sum = 0;
                    for (int y1 = 0; y1 < BLUR_SIZE; ++y1) {
                        sum += image.getRaster().getSample(x, y + y1, b);
                    }
                    result.getRaster().setSample(x, y, b, sum / BLUR_SIZE);
                }
            }
        }
        return result;
    }

    private static long calcContrast(Raster raster, int y0, int y1) {
        long result = 0;
        for (int b = 0; b < raster.getNumBands(); ++b) {
            for (int y = y0; y < y1; ++y) {
                long prev = raster.getSample(0, y, b);
                for (int x = 1; x < raster.getWidth(); ++x) {
                    long current = raster.getSample(x, y, b);
                    result += Math.abs(current - prev) > 5 ? 1 : 0;
                    prev = current;
                }
            }
        }
        return result;
    }

    private static boolean isUp(File file) throws IOException {
        BufferedImage image = new BufferedImage(IMAGE_SIZE, IMAGE_SIZE, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();
        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        graphics.drawImage(ImageIO.read(file), 0, 0, image.getWidth(), image.getHeight(), null);
        graphics.dispose();
        image = blur(image);
        int halfHeight = image.getHeight() / 2;
        return calcContrast(image.getRaster(), 0, halfHeight) < calcContrast(image.getRaster(),
                image.getHeight() - halfHeight, image.getHeight());
    }

    public static void main(String[] args) throws IOException {
        System.out.println(isUp(new File(args[0])) ? "Upgoat" : "Downgoat");
    }
}


@Downgoat是的,可以。我更新了分数(不包括正确识别您的头像的奖励积分:)。
Sleafar '16

38

Python 3,91.6%

用新的测试用例编辑

将文件名设置为您要测试的山羊图片。它使用内核使图像上下不对称。我尝试了sobel运算符,但这更好。

from PIL import Image, ImageFilter
import statistics
k=(2,2,2,0,0,0,-2,-2,-2)
filename='0.png'
im=Image.open(filename)
im=im.filter(ImageFilter.Kernel((3,3),k,1,128))
A=list(im.resize((10,10),1).getdata())
im.close()
a0=[]
aa=0
for y in range(0,len(A)):
    y=A[y]
    a0.append(y[0]+y[1]+y[2])
aa=statistics.mean(a0)
if aa<383.6974:
    print('Upgoat')
else:
    print('Downgoat')

3
+1做得好!我真的应该弄清楚如何在Mac上安装PIL ...
Downgoat

我添加了第二批测试用例,您可以基于此更新您的答案吗?
Downgoat

@Downgoat刚做了
洋红色

@唐高 pip install Pillow
Assaf Lavie

16

带有霍夫变换的OpenCV,100%

我最初的想法是检测山羊腿的垂直线,并确定山羊相对于身体和地平线的垂直位置。

事实证明,在所有图像中,地面都非常嘈杂,从而产生了大量的Canny边缘检测输出以及来自Hough变换的相应检测线。然后,我的策略是确定水平线是位于图像的上半部还是下半部,这足以解决问题。

# Most of this code is from OpenCV examples
import cv2
import numpy as np

def is_upgoat(path):
    img = cv2.imread(path)
    height, width, channels = img.shape
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 100, 200, apertureSize=3)

    lines = cv2.HoughLines(edges, 1, np.pi/180, 200, None, 0, 0, np.pi/2-0.5, np.pi/2+0.5)
    rho_small = 0

    for line in lines:
        rho, theta = line[0]
        a = np.cos(theta)
        b = np.sin(theta)
        x0 = a*rho
        y0 = b*rho
        x1 = int(x0 + 5000*(-b))
        y1 = int(y0 + 5000*(a))
        x2 = int(x0 - 5000*(-b))
        y2 = int(y0 - 5000*(a))

        if rho/height < 1/2: rho_small += 1
        cv2.line(img,(x1,y1),(x2,y2),(0,0,255),1, cv2.LINE_AA)

    output_dir = "output/"
    img_name = path[:-4]
    cv2.imwrite(output_dir + img_name + "img.jpg", img)
    cv2.imwrite(output_dir + img_name + "edges.jpg", edges)

    return rho_small / len(lines) < 1/2


for i in range(1, 10):
    downgoat_path = "downgoat" + str(i) + ".jpg"
    print(downgoat_path, is_upgoat(downgoat_path))

for i in range(1, 10):
    upgoat_path = "upgoat" + str(i) + ".jpg"
    print(upgoat_path, is_upgoat(upgoat_path))

这是不输出图像的全部功能:

def is_upgoat(path):
    img = cv2.imread(path)
    height, width, channels = img.shape
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 100, 200, apertureSize=3)

    lines = cv2.HoughLines(edges, 1, np.pi/180, 200, None, 0, 0, np.pi/2-0.5, np.pi/2+0.5)
    rho_small = 0

    for line in lines:
        rho, theta = line[0]
        if rho/height < 1/2: rho_small += 1

    return rho_small / len(lines) < 1/2

Downgoat1边缘:

Downgoat1边缘

Downgoat1行:

Downgoat1行

Upgoat2边缘和线条:

Upgoat2边缘 Upgoat2行

该方法甚至在噪声特别大的图像上也能很好地工作。这是downgoat3的边缘和线条:

downgoat3边缘 downgoat3行


附录

事实证明,在霍夫变换之前,中值模糊和自适应高斯阈值比Canny边缘检测要好得多,这主要是因为中值模糊在嘈杂的区域比较好。但是,我最初方法的问题立即显而易见:检测到突出的背景线以及某些图片中的山羊脸。

def is_upgoat2(path):
    img = cv2.imread(path)
    #height, width, channels = img.shape
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    gray = cv2.medianBlur(gray, 19)
    thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                   cv2.THRESH_BINARY_INV, 11, 2)

    lines = cv2.HoughLinesP(thresh, 1, np.pi / 180, threshold=100,
                            minLineLength=50, maxLineGap=10)

    vert_y = []
    horiz_y = []
    for line in lines:
        x1, y1, x2, y2 = line[0]
        # Vertical lines
        if x1 == x2 or abs((y2-y1)/(x2-x1)) > 3:
            vert_y.append((y1+y2)/2)
            cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)

        # Horizontal lines
        if x1 != x2 and abs((y2-y1)/(x2-x1)) < 1/3:
            horiz_y.append((y1+y2)/2)
            cv2.line(img, (x1, y1), (x2, y2), (0, 0, 255), 2)


    print(np.median(vert_y), np.median(horiz_y))

这是失策8:

脱粒8脱粒 下降边缘

轮廓(代码未显示)可以很好地检测山羊(脊椎)的上边缘,但无法获得整个形状。

等高线

进一步的研究: OpenCV具有基于Haar特征的对象检测,通常用于汽车和面部等事物,但鉴于其独特的形状,它也可能适用于山​​羊。

2D特征识别看起来很有前途(由于缩放和旋转,模板匹配无法使用),但是我懒得弄清楚C ++的OpenCV。


10

Python 3,numpy,scikit,100%

此代码针对单个文件名运行经过山羊训练的图像分类器,并打印出“ Upgoat”或“ Downgoat”。代码本身是python3的一行,其后是一个巨大的字符串和一个导入行。巨型字符串实际上是经过山羊训练的分类器,它在运行时未腌制,并提供了用于分类的输入图像。

该分类器是使用Randal Olson及其宾夕法尼亚大学团队的TPOT系统创建的。TPOT使用遗传编程帮助发展机器学习图像分类器管道。基本上,它使用人工选择来选择各种参数和分类类型,以最适合您提供的输入数据,因此您无需了解太多机器学习知识就可以很好地进行管道设置。https://github.com/EpistasisLab/tpot。TPOT在INRIA等人的scikit-learn(http://scikit-learn.org/stable/)上运行

我给了TPOT约一百张我在互联网上找到的山羊图像。我选择了从侧面看与“测试”中的山羊相对相似的山羊,即“在野外”,而图像中没有其他内容。TPOT过程的输出基本上是scikit-learn ExtraTreesClassifier对象。在对我的山羊进行训练(或“拟合”)后,此图像分类器被腌制到了巨大的琴弦中。然后,该字符串不仅包含分类器代码,还包含对其进行训练的所有山羊图像的训练的“烙印”。

我在训练过程中作了些微的欺骗,在训练图像中加入了“山羊站在原木上”的测试图像,但在普通的“野外山羊”图像中仍然可以很好地工作。似乎需要权衡-我让TPOT运行的时间越长,它创建的分类器就越好。但是,更好的分类器似乎也“更大”,最终在高尔夫游戏中遇到@Downgoat给出的30,000字节限制。目前,该程序的大小约为27 KB。请注意,“第二组”测试图像和“备份链接”均已损坏,因此我不确定它会如何处理它们。如果要修复它们,我可能会重新开始,重新运行TPOT并提供一堆新图像,看看是否可以在30k字节以下创建一个新的分类器。

谢谢

导入泡菜,bz2,base64,numpy,sys,skimage.transform,skimage.io
s ='''
QlpoOTFBWSZTWbH8iTYAp4Z //////////////////////////////////////////// 4E6fAAPR
OCLRpIfAbvhgIAAAAJCgAG68fDuYNrAwQbsADQAKBIJBITroq0UyRVNGVqljJVSvgAAAAEgAAAAA
AAO7AABugXamjQYyCIABQ6O7LEQ2hRwOdKSFCVuGgF1jBthaAUAAEgKGLVAAAAAKKCVFBIFEFKVE
DQNAaNPUGjTJjU000G1PU0ZAaaGJoyDQaDaQxPRP0oZpNo9NRGaJtRoaYmmyammnqGAjTBNpG1Ga
mT01GRoemTFNnoRNPZCm09pmP9VVVBlIgAAAmgAAExNAaBo0A1MA0ZAADRMCZoAajBNMGjTSntAC
YJgiYJjU0YNTTCYCYTANABMATKHInox / 7VSqoZMgGQaGRoADQaDTRo00YQaAGgAGQ000yGmjQNG
mQ00DRhNADCNAAGmTIZGgaNGmgMhoZNAZDIIp4EBNACNNEMmhUjTyJ6T0h6k9qnqbTU8NCnqDaTJ
oaabTUaNqG0jIyG0T0ID1BkaGj1ABoMgGggwIxNAGhkGmTCZA0Ghk0DCKUQECYBMmIEyJhlPTU8k9
TGmpP0NNU9tRomTaU9PSep6UeIGGSGJppsU9MTKbVPyFPZMU8ET9QmmnppiJp5TT0A1PNSeJknpH
qb1T1PFGnqeqeNTSemyaT / VUEKiJAQp4JtJ6iTZNQNMgaabUBtRtTymxDUaepp6mgemp6ag9I9Ey
aaM1NGQaaDQ9TNJ6hoDag00PUaA00PUB6gNGR6jagANHqDT1DTTI9J0gKvsPxi9r9nnM1WbDVUTR
nBgijNiWaqCjE4kzhxREVREZNmqgdLCqGJUXEg0K0IUotA0AJiVHEoUpQUI0CFDQUFAlI0FUjiQc
SjQA0DRTQI0jSJRTQLSrSjUQlFBRSBSNFBQAUo0lA0CYjECNjAjiEaVChEKBKUCgxAi4gVxAA4hQ
cQABGiIMAYEDMI90oGBe6yPBxuR2XhdxeZ1XL5AOe46 / lgb3BhDEJzJA3cev7vi53o25xTVTDRTL
S1W9eT6bsd7nyJqit + oxYIxWMYiKoqLGDERRMbmDk5 / f6rkb21xwxXFwxJYkqLFNSVjGDBjFGIiE
qiASEhEiLteHuvnMwqrqQgKhgZCZiYGIVCJEec2WyYMxkzjDibGEznHXdX7PtN84txMODGGnHFxY
GsFUZxYzGSoxZjnNNLO / 3fouWnGjjcYxnGCc4xVGycVFEZjDZsNpgzOM4UxIRQSGr + hhCVYTQEJB
MhACqGoDJDAR + C + VeBCIQEqhACCRSMAEqiA0MARCEZiZkNQiKEJACuhYhx6tAQhhet2tXbimsqnn
5qIY9C5JNHDqZp2rlRGwrWGuGgdu4FIYehsHhUKrgtTZWLIJqoOGsaUi5c7iYp2n + 46rbNtk8pSy
TJoqTh822poWQW92oaGuNk4 + Qil6VnzEKp6Lla + yUQqzH9N4p / vcI1WYVfBWLk53uwVcjn / iaf1x
kZJRY15LvF3c6bDSd7rtIF / CIeJ5ySSPDS8WpbhSth1jnyu1DFRb7ulLM6NlFMEVOCorVWdxjepR
5Nc0vgBvyASUIIJt9qydSewF7mdm76qnXx7NXCsl8ZDDG2 / 7KhXbsv3S1dTtXOitVYaUPrsnj + nG
R1MPnB8p7Hvdwe4eXxf1Bf39iVuyg9r9aweH4Ht / NfXOQ4IJ + q9UqxkeHy / Br1ixpI39nqf5 / 4gm
+ LgfXIgl7f372D + vf7 / 5D + t8jLCs + H23tsPj / lnZBkV + Xn / mfuvf + 2anyF + G + bGUypcqKqpb7iCo
QlBCSaYTfNYNeoXO19viV + uYu6lckm6OXj9Tp9QzdR204Lp87r88k9ULU01rhNPleSE5XK01Nht2
wB94gHbgH5aAB / 4hTt + y3OP41ivChK2SdsxThs4cw8p2uVsN5FTvdbYyDqkHKOdv6MDXJtk + fP9U
5DFrCIhv7UQqmETgJWZWhQhDBUKlJVKRuLBari0uxZtg9q6L3K42KgbA1aXeD3ypsAhWxqK9TK59
zuFDq1sYAWeBrNuydhlVPhwDoa7rs0xZkRXtSwuyYXtqIGsoWv3eglDKBjICrev + t / pew8 // j513
S4f9JIPxCWiAoDeb + iULXivpuL37uuEfiPr764B8OuKs1SrGVPUwelyHbu0yufCuMGLcP / 3fWryq
1UsZhJYJVQkrsEZBqJpkqWQiaYqbW9MsHsp75bTgxTNiy1cdasS2yU3GLG1jf1ajXwKd + 5HugAoU
tkoFOFTCSlQpUQxsyVjWZPGsCg9gt9j818V6Kvl7v5rK1tfoqfGfF1VAAENVQVVB + TUgAKqgAArd
D3XFc7OPq9D / bjG5yjUJeo + UtdmF4WweIIIipSUqVK2ISSVr93 + lkXLVyElqLZPL12cp3sc1CkPL
5IwHHuctF9lda56rrWDJy / ueRIKFF / fVB + EAAlCWZzg3ywLIOUexFPhVz68zMJ9jK2cpO2Kkma3p
StTr71R0nR / Gqfiqg8EojIZ3LNE7UrqlPVIysrlogNqiJzimFb6yLlGnVjHz2EdpNV6XZ8iv7IdT
nN0ut93cJpaqV0cEixL2TzSPqmoXvqB6IKDm + qmocLKnh2CWwsyqsMHtlV2 + rqNzX3nVoN0Cg6vL
U2OQyZ + xMs / gMc8yPKp5AIPqjjxNohmUc6ulA8IbleVQ2twH / Qc + H3QukwweIdinUphR6cPtB8oN
K8g / jbgfO3A9NhBQDKIg5IFDqBF2Yg / kQT0lA9NUPUVfVEfWEfpiJ + hQ2IB0oDtETMCZdHXCfrQN
qrthLhD0RNcJ6Y9EulXUgXS + u3LqAPVXav7EuHVO3DzA3D5IeUZxJ4DyIIPZ5HqdwIIAjH3M3O7T
zfUe5873xTd7r3pwJvknerhHzvPn6vzoOpfBAxna5nUVkZ3qsbqsQFQxLQ0IOKkjliCAI5znlbm5
ub29vY6oAAAAAAAAAAAAACqqqgAAAAAAAAAAAKqqqtgpqaM + fXWvZtXPp19ObTpWRyVSVzSaTnSZ
ISFlhCDkJ0WkkILE5KpK5pNJzpMkIm96uSToJKUXRg975M0XKsINJzoLBlWMGQ5RR0nKkFlFyRjJ
ISi6MHvfJmi5VhBpOdBYMqxgyHKKOk5QEVdE0FESD4xMmcIxOCC5hcb0F7mAXSUBk6EEkTEcoC8E
QpGkCSBCaqzovVoRckouU1WMZM95vNpRIYxVQaAgxG50kKDifCRxkiRWKxU3szGLmZHqkShKT2Fo
SIIujEYQg54EMjYyhJ5RKKM2hqbDJmxkz60YxYmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVVVVVVVVVVVVVVVVVVyygAwAAAA
AAAAAAAAADGQAFVVYAAAAAAAAAAABVVVQAAAAAAAAAAAAAGMYxjGMYxjGAAAAAAAAAAAAKqqqxl
yZAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVVVVVVVVVVVVVVVVV
VAAAAAAAAAAAAVVVVANXYZ9XJsNOhzoPjATZ7gjJHGZqZvMIwUCNiA3ON7mg8lirSKUQUpMTI0ZQ
NxorCSQKMFRGdFjaEZPhGEoxlKUgAAAAAAAAAAAACqqqgAAAAAAAAAAAAAMjNnzZtbNq6 + jLp12r
r2pm17IyPWUke6TzZ7lg4jfIoCcieoRCAEiwesXIqSVnqmaamnS1s + tra2wz6NGfV0Yy5cmXV058
2tp06cYYAAAAAAAAAAAAAAAAAAAAAAxjGMYxjGMYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqqqqq
ZcgAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqqqqqqqqqqqAAAAAAAAAAAAAAxkyZcmTL5X
UABaQRUCkFAEpBFgkAQi / yAIiyQorG8kZN9kMZMAVA1v18dKaO4pB0771qIqBiQVUIgVU / 3hAHaM
ggEApEkkXUCueVjqIqwv0JBQVdUQaqXTh01SUQosK + NiU2qmwMHABALMSQ + BUXW + 7Xr09DlfqrdX
/ 939Xyc9YbJ / GjfTHd3mflYe8dzKSXup + r / HbwMZ8arVvHPdveWSm6FplrPLVmr2S843G4vE5O65
PJ4bC8DU5Luf + 6ve / Xp0 / g6un0Hj / Ty0fn2O99Haarbd32V / Dny / Qc5sNf / zt7 + dwOVu9 / 5Os2eg
0vXc5p9t4dmD1nVd / lairac3oOe0vZ9V + fSdb + LsOvxsPp9V1Gn8DR6 / Y / 7 / prP + 7La38WU / 06fv
fB8TVaynfbXa6qUu6xdNqP7 + FLY62em1Wnydnr9r3vjbDxtXkWeFrtT / nW63X6zw / E12s1 + Vsrk /
H2 + P5HkY97JyLvk5F6ud9cu5OTj3NtSvbUrsvL1VdclKMCEI / kz + htbPr46uEYwjGMeEz24bnash
zXEx3HMzQQZAQYBB9WpqbuxABZyiDy5zuTwGgskeZ3vWc + ABzZFn1QCDPvZ0J96TVM1ENETFMVSQ
UxNFVVRK + 690eoABfv372329iVOAmoTnKmXpwCVlmZmoABwwAAAORAAzRmgM6AZ85kAc2A6TpQ0Q
AAAClc5KO1AHe90CScngj / ABrQBsQABkXAGUWSrUqVKl9 / KLRiBAYDByIgJv / fkVEE72ARUN6QQT
av4jrx7Z + ANFQeu4oaOQ2IIM36MBCY6 + yU8Yn97qjqIuOZ + 9iKAou4t0QKchQhdMMYRhCMLUcv + i
EQABvlVN9lZZYknOaiSc9 / oX6WU4KgZgAAAAAAAOS + kDkWdAOdAAwgB98aQAAB + 0dmnKykqA7gA7
w7yc1kqA8EDXNWbB4oANoeQLuMAF9XIowfMQzlqMIWrUYxtWoQjCNq1CEIxtWoQEKRQoVCgAKBEp
QKBWke4kA9PC9hAIHEkBD / IUkD2TCAb / pcCjmkJd2AO / lFXsIR35QfWwi + hkF9fKi9rCIie4gRfE
ym3CH3EHl4A9hKhxJ / BgXBwisStCQLDeYA3MB6cvZLeLKyyysFJWKUJMzOQHtgAA4gA + UAHIB9EA
M3ywBy + eAAwh0AA6MAAaU6tpQkUTAAArsropQAAA14AAMYAcbi0uNS49KlS + / Qygn9okGIUPw6YE
HpA8SfNPy / H4T7sxEA7lBBAPSIIKtIVMa6caqJDD5OfnbqJb71tVM6zwsIQAUgIwjvsAywAMqeVX
ve / 3pznOycydJCjgZyTUAAAAA + gD6gDlDlA5YDPAHOgAYTQDog6M0QBpANIB1z9llcp0nR2juO5A
AqropQAANca4P / DDADGACtWDBhnIQjyV3R / 66ny2rhCMIQh7rcOMh + Hynd5yMPK5XGdbifY0PcR3
GEI6fh9yjloxhCFqEIQhDeoQAD0YJX8q / evb4nOY3dZSk5qMzSmYnOgAADh3CgOJAA + eAcnyYAA5
gAz4wgAHSgNH1BogAFlcp9lMHagAWJaidO + AAAAAAMYACsGBCHpIWoQhpIRhDP6HjctrOQ4o6Lzb
P2RpiYdZjQD626Ff / PHsBn37P5PufLqbcUiBgCMIb3CAG6gC / VVOq9esSkUoSpIcDKyb3GZoAAAA
cYA4sA44MAAMAGdObAwQYQAH4OnAA6sdWDsHX35Uk7GgAAJ0lJRqQAAAABdumMZDbAKxRgxhnIQj
nd0ydDouH8vuGWtQhGEI6jwOK7n50c9L + 2b4 / dPObGELUIbrGEY2oxhCEN5iPNAD1QXr053vTWWJ
SoUskoK67KSAcGOCe + AA + IAAAAPrAADmgAMIB + M6I6YAAdUAdZRKnYzoDthpgFKWUkoAAAAABcu4
wAFaQwOWhCEYQjajGHm / S8dGMMH4cYwjEqlQCFz / 4edmzVADd7iqXwZpGvJyp7vSne5fDfw4NF8z
DLQjGELUIwjHeYwAADb0pelJOe7ybtQr3idApNwGYAAAAAfHAAAABmwcwcyHMgMIHPujB + UAAaUA
TlNKgAfy0wEpf1SpQAAB4oABjDGAVF9WKMCHFWoRhuXv7UIxhCEPHtRhCEYww2BF2WXkBAfUgEZs
IrLoyRRB3bAo6GrNSCDMZkPwHld4ZXqqfWZHDB1X8PQ4ftgUL2AQAJykYAAZYWWTy9 / fJSpOc92m
KTpve9Ue0nOlFAAOGAcJxYAA4180ADNgcqAc0ADnsIAB0wAdSAAT / dZOUw7XtjtwacUknKYAAANg
AAMYAOLS43x0qVKl2ZnoEoqc2QDW8f + sTtv / A1AIMUSdJOliTgaTCVQyOZxmCx6B7fdTji1wIOcL
QRhAMA0qVKupUqVOAX / V36qqqUsnPelCuzfqTy4lKlJ0ODAAAAAAAAfXA5MAwQAMJz4HQh0gAAAC
yVkqKABpgJqamlGpAADXA8YAAxjyQF9WKMCDkBWBo / f3nATMdNqPaFDUAg3zQSIg + lM20pcyohl9
R0H1pgoVnawZP7O20Wvxf2LML7Co6hNxCoxEEREIRjG1ahHfoQAUpSlKZErMmyuuVlcrLLK8zfvV
11VZV / 2d + / Vl6qqqvd5iqqqqqha
/ KY + Pj / au3bt27dzdy5cuXLlzBuXLly5z9y5cuXLmguXLly5tOh2nRbTabLF / Nh7PF6XF0eLi4uL
i4mJiYmJiYlvY4eHsuuw7du3bt27du3bt2 + 3t27du3b4HA4HA4HA4HAu9rd3d3tLu7u7u7u7v2N7
7G93u93v1 + rB5b7eYRBmhGtRBsKy / GX7nOB1 / E3 / qXrb / 3FEEsgr3NOugQYgYIUoKUpDoMnMf9JD
lIzzOcRB8V0nUZ / J2IjPhEeewNb0JbaLYXfo9aPzTK2tiN5ALOEUiEbNlrUDRlB1MS + eEEA + BDJZ
+ PbCQi4er6zV6K2iiCwOAQHKAQEIQIgsK8HQmk + 3XIg4AbHDyyj2C7CQc / V3ix6TAb7qDRb / pOt1
ebs0bSBiBYgWQEG0bTBQpV + hi7qnVA6OEHS20 / p / 23o0fEmnxQ1qhXQKQrW1g1sHjQFrLvb + iAWn
lK9nsvYQQqUWDrj30rLLFl85s4pl / CToEB2gAIQS7ZrwaSB08E27237snaWSIO7jXauo4q + b4OeE
KpUKxq14UISbjbs2RBAPUU1ezYCbpVcJlh3K9CL7 + BIebaJl1OUvpTI + aCSVpzU + Il8r4GQDpJoG
gGgR2en5fPQIPnu4x7XtkzByrR1QKTpsdMNCQYt0AaIlc2aEEAs + qCTtZfBwYICmu4fpDGr2Hjae
psCC2AKD6apD39bTAGwy + BZPQCAWOGWUaOFSbfCbMAyqoOAQQ6SATyAMWOZrG0hbHBBALXsyTC
ZJA53b9jyNZQ5HHH2ZGk / 13f / C + I / ZDte08YgB0kqUgG7pXT1ABAMX41Lbt4d1gi3BVNUKwAEJgH
cMJzQVfUq / x8 + DBFgv12VXO1Fpoq5i7xXVgVAAuQC4o11H6opZ07GzB1kExvmeWckaqbkCRU1iJf
Z9gDVniZ8XUg + zZ2lCTCU5qcdLqgrZ84SqB + ​​QwNCdQVw8ADECL + / t8zQ5LrNT52orqvD4m6lPzd /
YyoxYg4ob1W / JpNtsPQ0XLzgZ0JpghiJlAIcxjlbbdBBrtkMjU5 + BG6 / xqfFgvYmQAvbmxoIE / cd
BsOq6 / jpUl4ocf6meW7vnUb4YhSRX4MLMYHhJd9wgEGFLb6HBn4AED58IDj9n4vX7m2oFVibn7IE
/ RTRnVikkSXY2vf / PBBqNDu / IurbDfSqtJv8Jlu9zNdPEr / OYWQgrECDIzfa7rEYsmcgAJgIADr6
a0BBzs9qX3KO1uM9LgaY4 ++ vIxTUXMFjPWNf / n38HGXqT338kv9mub5gWYIhjiEEDd9VS / QgBAP +
UaOqjT0PBqd3W1BPQqlPNiXksoF4rxC9wqpwa6mmggb53q4Krla2yg58EZ5RfgS1wDIgOADyo6q3
fostZ4HbsAAgHi0VzeKH / GVqr7zs36oA4UJLASwUkjJSX9EH0vMrq4AQdzftzQzEGxjeY48XN7Ty
9eIT2vRrwdhb1lbJljEebtaNNsuay9FQ0NROIeNOzwh5q6ryfpvXeFFDpIApEPrRApghYIiEFM32
n1P8enSqlVMLPwez / + 7nkJ4qn04P7wd / 3UgIYz4JAQ9LZyKDz2ckVXrtJc3PJ23yu2 / pRB / VFKF /
PAnQeXIIa + BU2EddC7OBF4kAOGhK3F5nm8SACAVVZvxO7 + WQArXQrfXwkJA1bgDqrQsJlycegjze
PWc8RzzpycDyyCAe9lBwpbONqF3TcfVbssZBWPyz8cvfwXwKSAUhiQm7lasRaEEUiBQv4CRCK4r7
0 / ZmwmS5Ks77D9zvJPwJPrQK5P7QZpAF4c2zheVZwLVWQE4ke22p / W0HA3mMM + PEpCsluAVqaYux
hkHopROiQKJgKQH6Q5nUHhx7f4fynJHZ7fv + NYbllgCn / cNUv7bFd8 + qFgeAvwB ++ ga / JVNTGN53
IB4WRpQQoiVv4Q60XPHXjmIfMQdt67x / xno + j3jw8oPPoFGJxUoBg3qTG2R3KnRoEz3EJBVwrSlW
MSllN0Ngn4X88TZSSn4yioJoJgwC9nXql7l68n50Vw3ZeHSYAIB6GcHhVyOzlclfgFIXgBwAUD0Y
qE + y4AQ98kOYiVVDEicHJ7vf + f / 6Pgus8Aem43Udv3PNO76n0KYLyZ307TUBna8nIWynQx2oTMU2
dsCW8ItuBERCQQo2 + uuJ1R6nNjqxu / 4477i1foYXNYL16lbIPJgNFAcpJfRZqXv1an470C2sEQpa
qB78062iGy5rWmC7XNTOQxcOtlMlzPAzFbXONFWMAeiwgicygj / F8w / kEh / BCEBCCQe46qXWreFI
F9y41ErQyV + zGVIHdiQ8IdgeFAA0ENQYGGVvxJAfiSfaWnSggzfIveHGXibYPW7g3HaVONwuUpvX
+ TONfVrNC0QkhtuZpcGy9yii1YMQLNs9b6FS / J6TlPa2Vz8HueJYtMxYgxlY / Mxw9k5IIDkEFxsu
5pMlm13gS5cnrZoLfi4MJDy7AhQA7ANx / 1w4ckJIIn1dz86i4qNLZVG313vETqtgCatnCWfqa3 / V
aiFaoGPVKE5fBeh5cXum + GP0Xfqs7d84PpzfD + lVlIIQQECDekA + 1 + DmPqshl7IBv4LPAN9U4Hv7
kyOuussZHkeXSmLJbEG8AN4AdTJ8SHas8Lh2FO7IK8BfiEAB4gvFuCYAAMyCKwAWXxhlysSbKCqO
X5oEwpblsAcWnxmbYkhsCF0JLXTv6LC + L1sfO1IamFQALWhg0BKtHIG / pvBjlrCol / RGt72YlSDM
KgEqBPTxHR / 7gUAYIwM0ur / 11xYqAPq2AWj9vikGf8kgnEZfBftker7vGEYN54bYwDwMwPr / tvqe
78KJRD / L9r / 4vUG + s7zBC + skgZJj9JWq / MFXMd + t6sAYegSGJ / eoe4SFUEahIxBDBTE1BCJREQVU
U0UjMRUVIxMyITQjQkMTAyRFUQSoRUTVDUSECFCWoyBFIyERREIlav87qAiIuAhiVRkggn2JmQqC
mggioJIIKaihqQIgCBoq1EiKJoimJCBiaiKiImZGoCAlsO4Q4pEERVJBBCI / bsYKjMokiGDVMgMx
EqsbGCiCqZqBiZMpmSEjFX9 + Yie5UICUkMTNDEEUEGpUQkQkU0QCIiQqs6pvC42JIkSiuAMLIh7h
cZKxi5zGRmbjBlfkNThAh3PMLQJO0kJFVCY1ZjISNVMFUb45gBSU0FGZ7GfzasbgNWogMLEOxBiA
3rG1wILGbnCpq4xVjARnwHiDkCwWAfxaEYGKrctSJxcgkTHw352YiOM7UEkEEZEV5xcYEqgL4vLJ
lQfG5rWIQgJDVv4WZ0YH / UOBKMg1ICQJ0ScqApiagQi9UNwQOy2OOgHJgSAiipcTFMahJWqVEPAy
OgyCCIMwImrAQMwd8AsnblR6VGR1PQzA1mxoQ1UpndpufbhB + JREmjK + ZhXCwnQCQUzyo + ux9AvZ
UqRpnWxAQiNeRA4T0JrBB3hgs0JhpI3389AitYytiEql9bdeYIA32QwUAiJqUTuVAMSFRW5ArSph
X2wycKGIQL + 9E0FImZkAju3G9BgTj58nLbRhhLLaavCpqgl1lhwYHDMQ6IdqAJEDXb2mC1DAiQwu
QgG3tDdTjjq2TxeQQ497iMECvvmdg9JZvQQiuupKGgwcAkAiQhiRAICJkBCAliRoQXZi + 4bX6Qqf
54BVUVW3svV1AAGoDVQahr75ooWMQGImINv4HV + WYAztv1YFAagjjqoR7LekYVBEc / tyMXCATHiN
QB24EH3ogGK4HUFw1QCh9l + zAG4DhDKul9eOWUwAFzoYVdFIAuEKpeV2N0bXVBO0 / pp8g6 + hDST9
JX3d6Pdlm89PwsACoAq / D8FdDO3hpyAAAKkpodVQCtghHXJ2RErK5wbs9XElajJiizuE85V + ZXLd
Pyvy8xJOupddZ5jUTHTGEXWTNrTVo1k / u32XuDO8fpJRFzX2UKHpyclub3QmrRtnLDzSjvgEvvB7
q4UBLarBSmLSu2vTbrO + ZSbdTc6xrbEWwt8 / 5hTso2Ra / 0agqAKv3nwdsPoXaRpJHO045EGgd72y
WrVszfzjOcVKkDCwEOIem7nv2gYPreIIBQhFovlA5DCNUYscEiTK / 4V0YQc4zKxElKSGrEyJBRhK
PAJTLfnOXThkGrlpBRKpW / L4WpuVL56myXL4dfGxr + vy6pUp5lp8s1 / 1ouKjtqrb + 04ioBfm1QTY
SIn9ANIpl1WXToEahjlGBu / sZIfKlLC8pB0gZbEbvzUFDMBqCIh / tfpxRwgnx1 / 0uHx7RPieotiQ
BYWISqFAQhLiZnVVycI8REQ0Hj7lTBFPuQjs + e96w9Ab5IiX38YHg / 3D50OJjzJLSQ7bunfZDrrG
EZn35Y4fYQOEYd1c5j2D4nxPMEKJfASSWsDZqBSRwqEYNCt + 6A3vDCJarMOHPPGt513RieQyBFjJ
Fu8a7CsC / pILluBQEK4XWubGgI + Wdp5FnlHAGiMrrzB4ZyE2tsGErymPlkGDldlc1J56XsL3uXUGN
4DjdYteEsK6aeWGMHQvhmLq81RyULQkPDuY7gaQmBYkohgb3TU8TrR5gannWpg + WTydjeeD3uUNA
2z63a3xxMLTHLNaIGAYkiPGHTIkiuaTyjnXCZcOvY7rJsRK / kyXWF1YxE63khaonFdmIOIZCBo1S
8dCHtB / bqoGF12thHvgxOedj4ypXY29TNWidorby8bsa3O2fAMszfcuZdsYrMudt7PnuznKXFGfC
bs9lNAERIRIXFE0ZCnSD3VOodpzSGr3hO1zz2dgHNH8x1rpXbTOd4vwiltm22MIboTvvrrnaMgO2
aUPDivhZZyHjo1YkPjedqKEBPwIL1YXRJUN4K3AIa7Q1hIQhJ8H0mrnO751mGYvCvCzd2vFl2Kdz
OdQLw7uFY8JdlkTe6SrYxCCC0N + RR6sLKYFQXlbMGu3PePLKtVuWMIndDDyJhyYbAjMxJPCltbXQ
dCxqKt047xOWRCvM3MGssh3L0aVfDoQa9SUWfXJ2 + tB1ijxCMXFzN68Awy42A7yi6e / I33xXYdoT
Cum8d6bbsI9eT8sLTdZwmoT4dvbzhMccnztjnbArbS28KEPdhw2LxfhaIiQwEdrrGa23skoq + b6x
yQCRmx8d4NB4u7B3d + 1Ad2dt4TgUDHclmXZmD548bQgbpOTc + h89SFWFt + / dEzQZAb3K6b4FHr0P
SvWlxxUdgdRuFlIZb511xtsmHbaRIXHDLYa6LDjd2dd + XDnae3fkT + RhowXYlgvFLlArArdxprHB
2ei2bilLTbbjnrpPpjG4u87QzjfHDG2PQ4c + UoQoPQi1GAhYtCooqWg + D6NHfW98ZvmkXajLdOVL
OaV6zv3Yd + UOljp7RCtbu + lqpqTkvZOe8quNevfvRQr28tcNtN3djfIsNOr9N9rZwMCI4AwwZY3r
Q91OyY6Q0jpdcnJHNGg3wySm / Lpkcl48Uvzz23RAN6SUkZt / CCivGGMsQy3pe7grdOzhlr06hTIL
77MKXMyjnhJCpHpf0w1vhmIcRDqWPZgZpHY8hztyj35vV2lIQA6cuV1fHcdfO7ud3c9m8Oeuwhll
iFMK92ZjaMsN3TVq / G + zXvyhy3JyyyfQuVu2Y5gelrdnZ3T7Z + Pbj02HeA8dy6lvQXj1319C0s0G
zbp26Wd81DXlZ5Y7dl5Wk / p0xw5deRdeuXVvBQ7bKWDTinWO ++ za9Dl1UuJXX + V6 + RKp7Bfv58pv
7szEu293TG0Lru9g0jod / fLWW1A403 + VuWVfHw0vs6FXdDJewpvINawyIumNm3b3ZO6eWG0xo1XE
cJUttx1xnV07u0516EASDuy4aEZdfJsqePd437m32UG / y7e6mW7yV7hDndG5PDC8e3m2GEOImshk
XECUiDG7xwR1pC / ciBt3gQPtrMmIQ7xRKGCJWOC3YQCrGON3BFqQEAicIEIlzgdVVQBVrmgd4xAR
AOpkqZKQphqvHn5Bu2ivV6CMZaMmkoGXCUFcRDC3sK5VM2QUZLe5VxQLXLXTu5W2B4Bj4XePi01m
5xwxtdx4U8nrloM8OnjTyV9T35WDaCCGu7jUmYhk5SZCcUDIuN17rXB + c + VqCqqoB93 / 0 + AXy4cx
I4e + q + Rd + K30f + 95q4G + nT4Rv2MSf5wwSskQvMBCgTSN4jJ80RzxSTKq1NU5AFVpsg4AW / CmH1Re
pH1Pn + flms88wr + lKrN + 5N8RQXZfBc / TxbCjqbDwu3S2f3kk7C12cg / Cep4AOctOLvDbOWWGeMx7
LoaV2y1gWvwu63hPC6q4moW6XZ1nyryWuB7wZLgy3EXaaJYHOuxlwvcm6utwbo9q8DXKOG22mG
T09MXGGAxGkGt5ZzkRPtZTqhMYNi6l9j5rW / ohKV1dU3mteKvfSyL3uC8mihsFDw1jCt9bHS5ZQa
VIM05IlNE4ts2rGNhrpaYNzWnPme784eXaqimogkoiA + yxCQQwwGC / N32IVAM87DPdj + NQHqb3XH
MW + GtR3ZimnCBDwLaQX93rD5D6Pw4spVuZ9JRMjI6vQH0SE0jBgdWEHClL7KNYVAQYm0XXUBozO4
mthCt0gUb7K4vrlUpkjr / isfW5TseFDnDKusXXndg6ulr2yuvtJ5MkBrxMKWmN1uRWDgqnWs8mxM
67xWEqQmWSTuD5b / OH8o / eff + 7T / 39M37r + R5ZYZ5es29pvL0vZ7ezGAxGQze04l6pvaAIfElD1j
uyCH7BJW + ld3zg5AvvlZ4z + D9K64KWyiVUyrs0xR3pejvdT1tL7vah6PmZNWILx3wpnT2J2 + w9o9
9fCuoRHQO0QLlG5 / peu1W1 + 3aXxkPXmHfam6KyERpdVrPu5pnGHOVOc3WcQgcPaNzxtyaPPLKTht
7DHvt9q0ekL9 + WEluHldE34YQEFrKwd2PY1dpTRXuZAWFY9L8MOodeuGD91x19mmWSdmA8DDQYZZ
5SVe / U4Qz7cGvBwR8Onst + nLN9d2yVrySLwjTfAE4XUSWoakBBkcOFRabcn6x4dkVtBu09nsG / fo
wdk6w5YLFCjQzPZd + qZ4boVhDVya8A7t177LqyDwxCN9cd / dHbnJ2kHEG98rUjEIxg / tEQELsG7s
tqXWlZrCZSxIFvdDZLtMjK6ImxEd4V5IVb9VfKb8uV7WcqBdXMRWI5b3cd1RMN + AaYsFEbMJQzzW
0XjyZ4ZZynCyOGN3s / a + Ol1WQ7nVrJenDHnqQW5ZGFw0AZC6unfWLmJswO21wZFFdXzE9drW2XeL
+ 3x9rupyyfQLsDCg4vv7e7Ddm + jm4Yr3Z4xjwXE3jxBxEOqB6X0HU9SRUtBRRLHUtShCEBAQgIV2
HnL8NMveS9WDDgYzXXahUuBzXMAgkaFrxPU7dAIQCKmanmTNUEd + POeU5vi9BQ8F8dwczygPKPI3
k97ou + 81vojxP1F0z14zxt15v0sO7fY7PDVVUDAwMDAwMDAwMDAwMDAykpl56wiDx + X7nyOu / w87
VVRUM1U1BcIYqqpYjnFAdIO8 ++ 9Z + 18123c9z4ncBB5KCebkR / F9t93ke68F4N5YPxPrNOXzAgqK
IkgOyEIQgoQ4 + Ecqf7fxiQMzG4Dzq + Tc15Pv8WfiwVYdh2AY / Eu3ZEEQREMFlDDBEEctvdqXny + h
7vHA3fh4vt8xfP8ePyd5LynAFJ + 3Ptf8e9 + S53hiKGmeFogi4N7lelx3fFP1fQXfeclgOhp + L3qf
LPR3UIgwiDUtmDYZbbuXRBlskgmkgpuAigqeg4x79wc76P5f1Hq / bPZHv5zz9fu + 0yY8N0fTgekP
CPCnCegGfRS + NOdThqp4QiqIh5MkgA2srhW8DlKNBIAOIHLdehZ1rhPaf86uqfIIdkjao ++ JGo9T
w86Q0VNwuIOHhUB8Ry / M9Z + Aes / j1 + UjkpzxyapKT / XCGk + p38OyE46gPHBKFWigCuPMZT2NyOQo
D0g + i0R + w6YMHnJez6v2mTvUkcfAHuwFa1AQEhvRgwP0cDQZiTyfuZR0ZzJazX8HT + o + d2HEQEHl
dD8wgg + V8C8JhMUV5CznBU0kSTFERRQVZcOJiimqZrOcll0AQfTfyZ77AIPSgg752NKA73Ve41QQ
c7pv0hiRG0RBwq9jnAxxrY9SzghQwKEKGOIiDhEcojKLDJUWG9PbyPgpTThagHYQEaUAgG1dSTs +
oXMbdx8Plo4sCrEWA8F9QQO8geXGDtv7l0hCCEIQuceSfAsjITnK8GtEtmNfDVrtswvLoA3oggGy
AEAtnDgBAPbysjLWUGRMP39lpcPFNubLXsAjCseDiKeGPHtSnG1B02A3FnzXY27bkRFwFyfBj8 + R
fuwrJsqIOYmIgzgQZgIOB + LqPDsew8DsvYy3 / tWhPG1B6P59leYICPhlNfSOMAw5u1vbjyqOPIdq
Grwf9m8LwA7VLERweIe1VIJJJppJpHBWoW / uFtYQofc580Z / baLY / rcbfloWBaeQgga0RwJdh2h2
kh2hJMJ9BuuswPpY6f9sJKTg + dtQrAXANw5QCE95VQbSHDlyhDlJCaSSSYSQhdfEO0R + 71MVS0H1
fr0Iq8eT7dnneHUdxet // 3FjLpVfxuPA5vK6V66FHLYm / EAkgC9y12MngqL8pCfqfWqrN7gVMopA
Ktl7KyD + VWq1XQkhAq6E00wkEk0ZQ4WN8 + x7qsxHnhJ3HOftGUU00FkFk7wUhCp38yurSK + vlliX
KTHkDTt6gAHL4zVXzzuAZrZdF3fi7g8wAOq0IcQchff83wLVvY7OEtFGVkx / y73fCdEl8lkllliG
X5vZ / cKi932 + qA47TNANYKwHsxv1 / CrdJ4GU84VkMQH6ZRfkAiuqXpKo2B8E0LUFD + ECeVAMfd2U
lGnUr1SN96bNl2RIKsi5Vv8qKk65ZaTEWYHdMJz8GQMADTIBsOtgYFCAEF / wFR2NE1YzWGjZvIYm
JmwN3tt9sgI1 + CA93wQhG316TjKJdbFQD1QruumCcXb / 1T89JcWGYUqGC1vWFPOY2VNL + VnGUaxe
qU1ZldElC24hK / Zlr / kn68N99aonkCAc5kIDFRg / u3y5Ca0lAKQEBg0EjitScs3s9UWFaODgGFoQ
SoAYAUyD60EK6hyVeJV2nXubIAQC2rcrXMJgO7Wrzp2jpMkUEn21JIUvACkOwhpC + Cj37Cr7ndLb
VyHWC2rebx97BJWkOSHJFzQTpnLpSN1uL3qpGRkJvFEgA6 / 0UlFtKy9MbwFF9Dch6Cgh4PkCgEJH
Nb / 8mNdfaF3vfr7au3g2e9QY / ZvaEXsTXoqrr6Ki8AKcZQefTZ7cbZoAF30kOXAyCmFuIwF4UdLz
0wdAG + BTCHux7Zn0gDjB2MdwuKkEwkFDm7BQVG9SwqBBobKAEIC2 / qAkLTiVLH2CGVhR6w7 / zz2G
4qJvs / 4A8vRolTkZVBMIEHk / 0DY7B9m1HviOXEWHb1g0gDX9c4k1IQgnCpZb7goDH + EsATHHfW5r
LbGMAWAUPpdrgI6VRESgUKyE5IhMCUSAXF0OPutXyU / nldne719lra1OAJrDNoAcxAbsbiGwnR87
b212K + 23VUvGA31TynD + GeTAQd57WVlBBwfMfH2G9vVKnFU8bad5XlBJJEkiFq7dOqXbc5 + hUgkk
Yaa9Fz1zAwu94 + Q99j5oAB5qtyAfmp7WcjfbM6KL1gjHoSxkv5u99UuF6vpKFrj1olNXufcCSOvh
fd2xlKG / 7XF43ZAvvtmmwMSQEIN5zZVXBSEhR0z6p1kwQQIlMXAxuO6 + Sz0KSzlMz5WwmOP + 5Kui
qyT4ndILsW9CQYQcAodKQlQArUr + ssfHwtTCpILqqo / RgAn + IAD9mt / zGlUfQ + JjFIiPvA + ZQBp
NWASGpwEHoHCMCERNb2spMiGGdf5lPB2LP76yDuSA / RcQA3CtAvgCE0AXFBfnEx / JLzDNpVN + Oeh
RDKQomGH8ZM0NuzZmn79Hfc4YPup93UHasgv4QggaJHOn1EwiDfAQG9PJ / HYVl1QopWPXywz / U9S
rhfVhWVmAAfiHRe7oEgno + nUBx0EdXoiDg64EG / DBBsgg9aCDM6Oqmz0QfL8dEG6FBrs0iDwuvBB
7bTyRdep5XiYJve8Jn9x2GM6qbeJfw0cfXRFa2WDuk8 / cby9fjROB5FpqFykYm1PLvHxr9qmCrlQ
3MSgaa1zfHbyfH4DKpqUvbDard1K03Worpp08ulIiD8kBJ + xixlpbofFrr5GvR995mAmIg7LlEQa
3spgCDg7 + CD + JEG9DhQQdgIPiwQfIQIPnbrfHZznOc5znOc5znOcg5ByDkHIOQcg5ByDkHIOQcg5
ByDkHIOQcg5ByDkHIOQcg5ByDKpKpKpKpKpogBBm6P8NdyPJefd6HrvsfT2 / rcLO5bK + Fd / 6 + LKK
KpzXN8vf85ofW7rtf77ynFU + GBH + cLn4VHj6WRcDVAg1NyoDLWqA / xzf0dnh9zw9DlqpVTZe1pvE
mKqfhKA + rUB + LOQedMIYxhoxjAYgxJdnGCsYxiMlmDFioJrGMFNUUZYxeY8t57CYorx1nOCppIkm
KIiigqy4cTFFNUzWc5LLuin9UAB + PfrIJy6Pr + eJnNDmJ6W2MzCjO6nVR5IAKGIFqf5QCt0NykAp
yABANmbqCWA9SHG3q / fyKs8ArifkXP + VZ0r6UUrSp1SWcynqM3JfGGb + TCzdL5gKXUGufguANt9v
Ggo1uIp7qnq8YPU1TcaHnc60 / WXABx + o3NBl6vpnESB7Qe3arD7KR7GaKE0 / 6fCWKsuwc + gHKXeR
4VsFtjLcunY8sAnADS2SRNmAretAvcMkVr2Schn81VtvUD / snTAHjMfR7ALTtdjoLsSwiQDcVyUB
AkPgLWrSIdgKC8A5oVqH / dhxxcHj2dYznw2OcwKpyAXkyo8wkxm6GWybIiwjlYlJ8WGtsjSTLmfQ
YoltFrJy4WhtlrPd0fJ + 5RV7zyAmXXmQBz0Eb4IGo4j + HFyuxC5hmA + Lp7XGM6VBwKRtqmGZKoL8
Q + g1DSBrpMd / IFp + MvHBZ + JBE6kC6ANXFK2cfW8wgD0q5KxwFQVFWgB / mQaMAd56DKEBg3yHHvMD
hOJemYWGWffGSSokFQhNBj6gfMGpzy9QO7zQ5a8CFA98Mv0CgfzfuHIKdPp6gAPD8ABDIPxPP997
00/1 + 7Vf0M + oxq9jy5ThAnvnJmTj + 2OYOg5CZyJE8f + 3uXucXvDP9T + SDeO + ISnbL4bpVUABUYVL
7gXNX / LoTNp / Ym9nFudlNVYiRURymZRUkQUSLMrFBnwVWIkVPTq / 8u5U7jm / + IbMP2rfw3WSe55f
07XWWsziJFRHqfxqHNvwzZRVf3qVwc5C51vnWzfqnmasiQUz + G / fJRxMwp65aQcziraVQVB51ABt
gNsB7zG2DaA2gNsBtoG1BtQehOlzvA22DsB7TaByDxgdwHdyDsB1BgdQZoNUDbjTAzwZwM8GQG8A
zwaIN4Bmg6g7AcA4B0B1B0B0B2gdQcg5BwDug6g4B0B0BgbA25O0tgO3vA7gNEGgDRBkBogzwZ4N
MDNBmg + zPBlByDqDsB0B0B2wdNQdAdAcA7oPY7QOQfqNgOwGB2G9IbAd8HdB2wdgO0DgGeDOBxBT
g1IMp86u6Alr2mBsKcGoBlBpzpeXoGzgiImdM8ryUktMDWAzweZw + DqgayrvFO1YNiDUA7QPJ0Bg
yDv8AM8aHdnQHV2gddbaBtNAdm1zITAPADug7oOwHcBwDtA7AeODwA6g6g7AcA4B0B1B0B0B2gdQ
cg5BwDuA6g4B0B0BgdAdAdwHYDmyeDOBngyA0wM8GiDTA + / OBnAzwZAcA6g7AdAdAdwHUHIOQcA7
woodadAYAYHQHQHeB2A7AdQdgOAd0HYD6HcB3gdgOwHaBwDgHQHYDoDoDtg6g5ByDgHdB1BwDoDo
DA6A6A8xTqUKCmvoqUFKKkilQpRUnqU6k1SapOUkUkUmKTVNpNUmqUVJyl / mKT5qminEU21MKaqd
tqphT + HYG / FV2rh21OMpUKUylBSipIpOUnKU6F9B / UDkrP6SW8gOEGEPQ6gHrR4h7AexQYQd3VOQ
Q5kCey9eYBCoBYBqCcoNtZ7 + lYPlQ5EZ0fwSB / St4j013Mj796pDwCEQBm0CAgEgpnKuxT6CMeKs
kFMsHy8JQdwgqxELgrIaSywjHJLQubX1C7AyKXGirdk5H946pfTw / XYoSR63vmvLksL76P1OwACB
hBDWusoCggvyACoQSAQYV7Cw4CBAImcuMkZG4aSZTgFkAAn5LcC + a1Wyqo9CCRnc + Rc3 + qLLLcNC
uZhQbgEGoxHOdhRL8F8 / liQxLf5kmp4qe / 33a2Ifbq / iyvacKwD3hAA7GIHX6MvCCKFUwFNBw1zw
cTvqiTlOP9KfzgEArnQBgcS4FPROW2ZdJoXbJGrzV5UeSjVBoAUD6v679RAg7XKhiQOmHHRc / VE2
HDegnENsOjHiz4yDYdb3eNY + IESh7XQgJDIrVA86uvicQoRfF0tFcwWrKLp7OoFr1ihsAblmMh4p
uIrW8exXq82p07OUnfw07QdCJDy2FaHZNmQRhcreIP2XUqHdfXen8krrwwQP9yOMxwVANQC / z1vJ
IEQQGcJdetX5q2ftJ2wM9Kj + rngQmC3PhSSAEmj874BadAqcp0TGT0FW1eKpIrD1rh6p / IJJG101
lx8bL5xf6gL89IEAI4IBCSWG3OiOaUqTo3bqCg7zKA73qrQ7zbC8hH + 97gcnxYaafW7KAkLqugCA
AOkUapcHf2jLhgHHedVmxgdas8utk5eurnq4DLQm5q9Zq9R4uy5ME3AwoQJ + 6RGRCECRkJYCAgIZ
WWAkJaBBhQamA5 / H9TiredrDtvtaCZhRb2knhxvtzJ8wLQHVS5nbSXjlMCAwURQ84JAOtPEFc5vL
tA3y2anUm4 + KCWSD6Ao8fRFuTr9 + d7V1SYFXxsFzbPofblVbcAo21b3u / UfU2qy6y6f54Hk0IOq6
l + 722ZguAaRAOw7vtUyqOshz1I8bzS2O29n0Xe2YHPQYcXgIPAQAGt7kG8x7K5JoQiaRM7VI0tLv
IzZtYzZutjNm1jMDkGByGtFc9ZAdQYHUGB2bNSpoyA6gwOoMDl0JIwA6AwOgMDnQoiKwAA6AwOgMD
nSCrY5AdQYHUGB1dZijADoDA6AwOmjVMYVNFIUmKQpLMidOlIlZgpOU + XtLcv + Ro9X10bv9O23QX
7SXom0IIf3783F4pv39Hd5mApYbSLiSSEgXwO2Bh / X9Klcmc4s7ur8hIODmidLHN8l2Dzm17p770
nm / v / ZeD8VVVfAxiMRiMRiMRiMSOAYBwDAOAYBwDAOAYBwDAOAYBwDAOAYBwDAOAYBwDAOAYBwDC
mFIUwpEiHp5hzUO9MUV + evADDkp70VrEkDS4YAtctpD1 / JLDtsPG0gb / UlKiuB6Lor3bc4AayABK
2H6AIMv5AEGw2nTf19GskBAMPpNPm79DmTgiArc9l7a8F5Pn0kKRAg6tAEEgJwcU0AofWwmlBCog
aSYorSvhH0eTViKn + EVEcUjVghr6SMacICSGQegFn + errwXxHkzS2eAFY + kDmfhyVYaAHfOIWsON
2vIUbiBJz4GGp7J7ZmrAl + 8znekOADQSzQMmnd2djdZ2M42gxyWkpoS0Z / vz6iraIOyH / wgFImr9
HwOFslabdTMuJGdceuFXIz3k / HiqW5CEEzz + / 68Cx84flyhY57tPmrL3W6XTk + HBMuD4dNfyseDx
IEUgAJiBFRbZ6Ya4GTBJCu3aIgUNlzPNZMwD7e3doqIb0FU5NKLU36M1UcrY9Zasd000667DsA9O
2fezKtc0ACZ96QKVVdd38AfCG + lH95C0jZTjIjz6LPCndEesoM8EAfJwBU3FtBf8LbLAs7jxvq8Tv
qoHj1Pae3itldbEtbHIcaQtA / T2gM7Xy / l2IIPrHIq0YFyTSFAEghN6EW32UGufZb2p5n770BUPd
gGLMAfmgBuHBIQ6QPrac9eHQrlo346lJmu412dxLYjEIJa27hVHQ5WBrsGxeZ6EW1JTf / Ds66sUn
LNwD3st9HUGCOrbltE3rSsVdTqt / 46l9lVHB9IcEhNC5jmbvWBY8 + rEt2c + Jz1c0fcK2A9FcYwTA
A33hM4C9W90n4jy9xX2gHpQRxa1Z1rQoRoUACz3TvKeTcgKk2UWvmRgkhruhdfJB1LFUmlBvONB +
ogvCBXwgvXE9OtwY00kuCfLAeAC2cHo3Sc7Wnhg3AN3 + ejuKl274 + XOx8kGQLf5 / PZW4YNShBAzn
ZvPOAUxyGtz0Xw7uwfqxzoni0IADC8UZcAGqKHfASyl0YOKxbQqmJ6qXPBKbgCBkbvJZe38D4TnS
EnhPRyyWUAAZhmLoo0RIFrpIKAeTvE4ZGApO7IHx8pmW4B0cIyysrDK9RK7ldiJ2xH + ZDOqZwrV5
IWgGf7BHacj / zjs8ZbVBy9AUjrtH9JP5V7NZBeS4AMLFxmnU / 8Pc5vhAGd2F5ye7J4uNqoBwjEtg
DyjMXm4fg1m / FN2ThVG0YUeHwfbViOzBSZFVGnmIt6cOggOX3cQ / XPHXWqW8EBV1hQYuqCtAef2q
5lDUA / hV + a4U ++ br2PUbhM0H3qP0gPAmWccEEjwi1 / j3N8RrT61o7DlIYADnWrl2vfanPXD + wVxc
AHX9CiUM7sTo7RMmFosktmAOVS900leEdROCR9iM7Zs50p6PyHffleg / IdqBEVdI78gAIEBcqbA6
FAMB + eJr253U7kbWK / dO + z3uLlW3WIGwx / + / 6px9fuOCCh + AL6daPfFXSr5Wvz2rr / c2cTW1uwRt
Gc7N2jfXIEC6LC8JHoQxn8UlslTC12NnCT7 / p84AcFqB74ViQ2B / NAOGsjL7wADq1Y1idU0gXzgJ
z88WoQzkNP8l1JN28Y0ueW4fW + 9OnI4BN1nsGYrVnP0EK0Du4DLYPxZ6 + H5IAbEsqbE / AAaflq3m
9v0nPc5TZKryWWwAqe0CQEPCBjwEFLClfLzMRDf7YJDSfdpIGNKxkMtxQz5mVUuH8nmz7sA7IKm3
q3zz6tTuHKxCLJjIbhWPoQw7RfzxvrXlyRV0ErIXEc3z5Nu142U1ZEhrdds99MbUNgDHyT3MIDTc
WTHq8NW7x1yYLqK2g5n2gCWIAVQkoB9Sd9R8ml0EHnCQpfuAgkVF7p + hcu2sGhA7UHFb / K54c7kH
JT2rtbgiECCaa7y7a3AtQ8x / YnegM1rOa3AEgILxcTuc8NXIGxKAcmgcqncSKFm0 + GVh34Ks4Ca6
mLKrDRkAdJE7fvjlTdyZd6IZeFjoMBUr0Oss8GZIEA8JAX15gXYBSulrshIayPQtWZJwK94rAkiA
Nvf3mmAvGj + 2mK + I1rAkorUZmznVe7sM7WTagTq8TvPdsJyJVh2sWSQmeunSj + i4dOY2YDXzsRBY
H6cxvacIkQXGZKDpUABP8UcNslpUMFyWYINks4Ais3c7LfRktkuLU0SAM + ghrSZPZanGAPMBE + Hi
QzPqo1s6rtlvFSGZlBGUAXB2B60DBoBjeP / vQgJa5eDI + 1T62TF / 7V0mY39eHq8fr17sAovGM3EV
p22sGHrTr8poMFo9rlh / ekPpVtgDqcIkmx4AD647TveT4tgtIJd2RoIIYliGIUPWwPloB9vIeqgf
cw8 / AHwYBCsMtKPj4Q3YA1nsoFDkynvLIdBCq + 3j8iPGQAUCPgQqQBEVeYvbBQQdaLoAUiXpA06D
iU1wwBubeq + awjNNYAf656ARWVRVg2yabvpLxuu8n / 0m6PRdwus5QSfuMQDn9jvw8JQthjErS5AO
4 + lodu6lZ9t1fwXjTfZTx855NErDYAuLtSqJlQ2sWDiuttyP8zoxnrf4xtV + XlA / dKJXjYjA0q2t
41b0lD9 + Qk0 / iefL3GlEkAqkJFBsxOdndROfSLc5CczexkbfYo / qReS1WrbuyAHQB / Cr72MFRKrK
eZ21Cj22nfpw27rIBTJaAHU8e3azXR3SvGMvWvcZcAgHNdyu2shZN4zZOf3h6 / rlEPSuSEw + IEog
pci7XfcxtvD2oORT / k / YLQ / Cq7nu1pvh4xIZNAdgG0H0ubtGvpfo8bOEPr72fBeuzS4G7jMAcwWF
27ALsMvbKdiYk758z1fhZ2tpE582oakBCDQpYLb2f9aaIVde2s07g / YmQ7K / 4hMXjjv / vydgAAHQ
so9Qndo / gHfAMfN4bq559ZJvb9uXqspwG9t85m88P5 + Rr4aOSdOAgVlikVHyd2Ti3HmKBi / MqaDV
sL1wnAE / ugR4gKqO / JC8W22Jze5spAZvgZQABAHIQmjKk5GtKIji7fxd1TQdaKuPNiFUFWJS65ED
L8z9yBQjcAwxBBYEEAsH4A2Pyua7maKaRlLL19G3fKeTethH7eWqznAFAdIQSJG4csaHOYnnS / OX
OOHLz8lZFKrC0uU3JBd6GNU6sAhYHhEwgm3AHBDEV3azVaxnDsmWxXKeZ66gYHfVOQvAAfnmKdAA
BIEPC8QQIyeprt8vV1H5c5vaVWRPLOCM3l6atqSeFYOWBegAvIdAGgntK2Uj5vwFD4VlJKRlVC0J
z7nP3MFqAVT7rRek8F / zY / 7AZCE1Mrg2UBFgb3MwWGPk5njynv4mSpr8zgQJVAA5f2WelIGtynR4
eJZ7SHrvi9vVrAGyAhaHV1CaAlNhwXdaqGcgCRBIub9r50A4P453oWfa3 / f1novK3rrL0cO4g3SK
af + J5ll / sWAnU9Qg + 7GsMugb1ndCCCgnUIOCxgAps78HV6c2X8Pd5fpr99Tvf99P7ZH36B82eSfM
zPMVDxYTi4TULbd9 + HWsQBk0FnkMj7sKQBqbHS8W2fZvLjn9dn2ne1C8G8udbkfmv4OO1Hv / zKzf
W / 4AYYDnjbtA5BuaCPj + 2deggY + 4fpvWkp / 7SWnnYjYdHgsPzmsdvs2BQGr3 / iVIjIZqXj5dxXoc
QxEggGx2rMV7F88Te7m62r2tH5M7Oqu1 / VivenvOV7fciH0WjqZr5PVHvRXfy / olOD8Vzpv8KmJJ
GVj2z9btv797opNtz / ++ ljzO6sve + 7v7PIf3X + zwH / 490QCcPwaLh2wUq6aAI15GitK8xY / VBAmD
Y4wECM2NzkWYHL1PCtuLlm + KZ0fN2uW2X8QbS7RlG / 1hWL7ZKPCigVz + ow7W1exUYkkdhiNj1rhS
6aPGP03 + 8vp81Tydlr9vBVV3dtdNQeC9a7swGT7LHEKLnz6TbcjF6 + sEDIrebWc6 + symQJF8 + 0DA
KIQE9316H0UJ3jfRil5W0zvf / m96XYOGW5m + RA8DZsIaS1NVa8 / qbc03xlIbFgaf8czo6TwZy4Qq
6oXJBwkckTuv3j + TEAfx2s2lorR9max28vusi + x + UFAWnWPsdzOw5p6pTVKjx + FrlFxff + 0 / W8Z2
Pfx + lo5 / jvwnM3Ej6fonL / tG9Jb5lthrAMgMbgqyDfUELd7f73lQZ + kBSgP + 5d58WT9mRlNjT2vN
/ K96yv + uCy2PxPsoZa1Qdn4X + deSU7Mn1VyW9ymSQK​​fkeYaeSFbQQKvLHS8ezgjOE31LchHRplOT
7nwrrfv / VQ6Cevfo + 9LEdvZfx0PjiVPWsMq3S0cR9sC5ulgk4 / NXKv4aNFQ8 + z6Wja74nE4aVJGN
hax + pB0f8 / CranGLVF51Dbk9HG / bYcCo2Yk9bMrOGN6uh7hZNvCgkCJAEdUbMrNL3sh / YGOpv5I5
RL6cXmOAqaCWoDU7jrXfDDSWkkHmkoPI2H0TFz3N + ooK6ez89y49HZqWWzn / prn7z29WzUMpP87P
dR1vh97fLrzLn8QJe + FggQcJyeQOqBBoH5zrPAnmGE3UVGwbVa6 / OAt / wImAcgKDCXq4 / vZJLZ8C
O / 7L3zaNrYvjeRX7FlrJVvRe46TEw9oJm92C15gE5MLfFg4MgSJIqsL85CjaswBXvKP6gf8DQjpb
7bohufI7 / Lfve / V68Rt59Vw6Ccwklrdt3fWv4U9Ieqm + 6TBAt4H6i12qZuCaoPl01QZoD7VYqZSO
qqsZxhuB14YOQ2TqJDxrIupeT4ezp / e96svnMfH4HSdX3WTqPRTyrIkgdE / xfn3mdk3FEiamcZz +
aN4bEDzY8kLcViBKY0ADNEfO0FMDk3s + lVIqehPUL9zsT + 7fOu / szXSwUQiJiwSF6XxxN + zGIqIh
b / 2eZF1JSQHRInCCL8Kx0wCBSFH4kIOVRkINIwSrZp9MLEur90Z / lHg + FIfX25SLhuiTEUsxgSBC
W8u7Vyoa5oyOt47 / 9LW1jCRvAt9QHWIFoA4hPiHxKjYD4RKsZYYCEix / 7v4jmv / BoJ + w73wg17ei
UfWmS9Gym1Mvk6DIVAAA2dVFlODLKZ7CKFV2XZd8JfU3aSJdOX / 7CXC82dxOaGh4 / t2OkzHr1feY
3uchvA0E3hbXh / e9xL5f1NrmhDcAdYFaN3xjnWcGtPmboVrR + 425TFUK90qF50vGqFIQ8vB23tgr
hk + BmYDp8XppnmIAFVtly8H9CdxfBVdKDAfpCHsxgOg8r + s7TmgnFB4khuezp8eGRNAbDeBYM3k +
S0tX6iPW1vuU6PkPBhiN6ZbuWqEi5r8EgQxRdSMDrm2C2wJ35ItBOIAwgNYAwhzwCnjFYaYLe4zo
hUtVOw + SabSJGRo5RqKoG1ur7sug33u7uA6fT6D2EgmX863NQOqpYgC7iC1XuSDmQ8ejtoHUz7Xj
+ wAwK2VU4shsdl8KjrAD3Ec / x4iIhh6cfC / Ux8CaDwWCCEZNWAhBRwF2aHZQhCA / mrFo + vN / Qvbg
cEblqZlCXbDMb60IqgnNJUAjFwAQhCHd9gYGJYuGvqlApR6hSmG4n1IQIfSXftZLPZhCwOdMJARs
b2u4hFb2ggZGvjM / hJSUNI / 3 / f6ycRymgi4X / ka / HWKpUDqAw / j / jx7eXc76q1P2DLJI8S / a / nV6
S5Ud56prWfrixl + o6wtGlyvkOqos1oPAECxSyM5KaMCjlLFIDx + ej59Fkdf8jAjUZvw / yBT6ygvL
oeLO214jL3sfoifigCAfaz2OsowBeZ + rf2 + 6nkyfF09j90 + bpttxO3Hx14I5ct4Q9jH93j + nVR2g
hEAxAMQqkMKV / kWXwzc77t52KJz2q1zmq1S4G1x69Kz + oA / QU4AB / 2y1xh6PhsZtoWaHyDu0S5IQ
aSh8LeP31 + wIGbyOZVPkM2n / YjAUNv2bEHXhYHIFvQT9yf8RCXZd4vl6ASrnKLI + d2qYnNrUW1Ng
NlAj0rf5VkhJxFSCanG + iIcyyqL4qX9xHgAA + mluM1rrwAtLkkd1ofd87lZem + qk1KEb5dpDbi7q
hgDK2LduIJ5owSR57uIuyP6wkaW2JAprdq9w9EpFoUeSbl7a7F9PjWsiBmAgY3r3ePVBlVEoMPe3
O9cQdd6PWGEBoO37at + 5dF + QAGt09ODv53V / e5D1ECNjYVlx / s + fB3 + yrXxFKOWJJzXMe / Qtqhjg
IljLH0OeH6nbW3U5Tf78Q0uY6rxzGXG + F8C0K4a + E4nmxVxbwit7QEFOk2lfszEG + ggIIlbcPP6G
S / 84Fp8AMwakQn2JjdgACpWYA7bjIRrLGtDkL0EC / wzdu + ttg9GUvl3BuQv7OJHS9NQBw + YEEKV0
BXkDbI36AKvsHLP1g1 / iP8aSBr8podjCY2fuLHnOOX4sthQSSyUwlC97ntxmDg28dRtbzRuQ0wP8
3V62hO9nc7X9fb9fznzhRBNYF5IFEEjJQBIKIJmK7I8Xh5Pn9xywJX7HKInI9jqQQbwACgmCD1RR
BPBFEE // F3JFOFCQsfyJNg ==
'''
print(['','Up','Down'] [int(pickle.loads(bz2.decompress(base64.b64decode(s)))。predict(numpy.array([skimage.transform.resize(skimage.io .imread(sys.argv [1],as_grey = True),(24,12),mode ='constant')。flatten()]))[0])] +'goat')

更新:这里是每个请求的训练数据,大小调整为24x12,并合并为一个图像,便于上传/演示。其一百多个图像。http://deeplearning.net/datasets/http://www.vision.caltech.edu/Image_Datasets/Caltech256/,duckduckgo图片搜索,谷歌图片搜索等

24x12像素的训练数据


您可以发布您的训练数据吗?
qwr

我使用的某些原始确切图像是受版权保护的,因此我无法全部发布,但是我将其中的一堆缩小到了系统中使用的尺寸(24x12),并在上面的单个蒙太奇图像中发布了,这些图像应符合“合理使用'。
唐明亮

6

带有随机森林的Scikit学习,100%

卷积网是一种久经考验的方法,但是随机森林可以在开箱即用的情况下执行得很好(需要调整的参数很少)。在这里,我展示了图像分类任务中的一些通用技术。

我首先从Google图片中找到了100张山羊图像进行训练(训练数据中的AFAIK与测试数据均不匹配)。将每张图像的灰度重新缩放为20x16,然后将阵列展平以在2D阵列中产生一行。图像的翻转版本也作为一行添加到训练数据中。我不需要使用任何数据增强技术

山羊网格

然后,我将2D数组输入到随机森林分类器中,并调用预测以生成50个决策树。这是(混乱的)代码:

RESIZE_WIDTH = 20
RESIZE_HEIGHT = 16

def preprocess_img(path):
    img = cv2.imread(path, 0)  # Grayscale
    resized_img = cv2.resize(img, (RESIZE_WIDTH, RESIZE_HEIGHT))
    return resized_img


def train_random_forest(downgoat_paths, upgoat_paths, data_paths):
    assert len(data_paths) == 100
    # Create blank image grid
    img_grid = np.zeros((10*RESIZE_HEIGHT, 10*RESIZE_WIDTH), np.uint8)

    # Training data
    TRAINING_EXAMPLES = 2*len(data_paths)
    train_X = np.zeros((TRAINING_EXAMPLES, RESIZE_WIDTH*RESIZE_HEIGHT), np.uint8)
    train_y = np.zeros(TRAINING_EXAMPLES, np.uint8)

    TEST_EXAMPLES = len(downgoat_paths) + len(upgoat_paths)
    test_X = np.zeros((TEST_EXAMPLES, RESIZE_WIDTH*RESIZE_HEIGHT), np.uint8)
    test_y = np.zeros(TEST_EXAMPLES, np.uint8)


    for i, data_path in enumerate(data_paths):
        img = preprocess_img(data_path)

        # Paste to grid
        ph = (i//10) * RESIZE_HEIGHT
        pw = (i%10) * RESIZE_WIDTH
        img_grid[ph:ph+RESIZE_HEIGHT, pw:pw+RESIZE_WIDTH] = img
        flipped_img = np.flip(img, 0)

        # Add to train array
        train_X[2*i,], train_y[2*i] = img.flatten(), 1
        train_X[2*i+1,], train_y[2*i+1] = flipped_img.flatten(), 0

    cv2.imwrite("grid.jpg", img_grid)

    clf = RandomForestClassifier(n_estimators=50, verbose=1)
    clf.fit(train_X, train_y)
    joblib.dump(clf, 'clf.pkl')

    for i, img_path in enumerate(downgoat_paths + upgoat_paths):
        test_X[i,] = preprocess_img(img_path).flatten()
        test_y[i] = (i >= len(downgoat_paths))


    predict_y = clf.predict(test_X)
    print(predict_y)
    print(test_y)
    print(accuracy_score(predict_y, test_y))

    # Draw tree 0
    tree.export_graphviz(clf.estimators_[0], out_file="tree.dot", filled=True)
    os.system('dot -Tpng tree.dot -o tree.png')


def main():
    downgoat_paths = ["downgoat" + str(i) + ".jpg" for i in range(1, 10)]
    upgoat_paths = ["upgoat" + str(i) + ".jpg" for i in range(1, 10)]
    data_paths = ["data/" + file for file in os.listdir("data")]

    train_random_forest(downgoat_paths, upgoat_paths, data_paths)

这是第一个决策树(尽管由于模型处于整体中,所以它不是特别有用

决策树#0


这非常有趣。。。您的训练数据似乎比我的要多得多。
唐明

@donbright我会发布我的训练数据,但是包含所有图片的文件夹位于已损坏的硬盘驱动器上。如果有人野心勃勃,他们可以使用反向Google图像搜索并找到我使用的图片。
qwr

这很酷。我下载了一堆图像,但是我花了大量时间对它们进行分类以获取“干净”的图像。有趣的是,如何无需花费太多时间进行分类就可以基于更多的“脏”图像进行训练。
唐明

@donbright我相信更多的培训数据和多样性会更好。对于“干净”和“肮脏”,我们可以使用数据增强来创建“更多数据”。
qwr
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.