Upgoat 또는 Downgoat?


309

염소 이미지가 제공되면 프로그램에서 염소가 거꾸로되어 있는지 여부를 식별하는 것이 가장 좋습니다.

이것들은 입력이 무엇인지에 대한 예입니다. 실제 입력이 아님

입력:

다운 염소

산출: Downgoat

투기

프로그램은 최대 30,000 바이트 여야합니다.

  • 입력은 전체 염소를 포함합니다
  • 사진은 항상 염소를 포함합니다
  • 염소가 거꾸로되어 있으면 출력 Downgoat하고 그렇지 않으면 출력Upgoat

그러나 입력은 이미지를 입력으로 가져올 수 있습니다 (파일 이름, 이미지의 base64 등).

요점 파일 이름은 단지 참조 용이므로 "Upgoat"또는 "Downgoat"를 포함하는 이미지 이름 또는 기타 메타 데이터에 의존하지 마십시오.


하드 코딩하지 마십시오 . 지루합니다. 완전히 시행 할 수는 없지만 멋지게 물어볼 수 있습니다.

테스트 사례

이미지와 요지 . 로 시작하는 이미지 downgoatDowngoat출력되고로 시작하는 이미지 upgoatUpgoat출력됩니다.

테스트 사례의 두 번째 배치 모든 테스트 사례에서 이미지를 테스트하십시오. 이 이미지는 jpgs입니다. 이미지 크기는하지만에 따라 다를 않는 정도.


참고 : 답변을 수락하기 전에 몇 가지 테스트 사례를 추가하여 하드 코드 된 답변을 피하고 프로그램의 일반적인 성능을 점검 할 수 있습니다.

아바타를 올바르게 만들기위한 보너스 포인트 : P

채점

점수는 다음과 같이 계산할 수있는 백분율입니다. (number_correct / total) * 100


1
"피팅"은 하드 코딩으로 간주됩니까?
Nick T

@NickT "피팅"이란 무슨 뜻입니까?
Downgoat

염소가 올바른 방향을 향하고있을 때 출력하는 모델 (방정식)에 대한 @Downgoat 매개 변수가 나타납니다. " "피팅 (fitting) " 은 모델을 전체 데이터 세트에 맞추는 것과 일부 훈련 세트를 맞추는 것을 의미합니다.
Nick T


29
이 솔루션이 한 그림에서 두 마리의 염소를 어떻게 처리하는지 궁금합니다.
다니엘

답변:


293

수학, 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 동물 개체 유형의 다른 일반화를 나타내는 지 묻는 등 여러 가지 방법으로 개선 될 수 있습니다.

알고리즘이 염소 1에 대해 결정적이지 않은 결과를 생성하기 때문에 첫 번째 테스트 세트의 경우 100 %, 두 번째 테스트 세트의 경우 94 %로 답하십시오. 계산 시간이 길어질수록 100 %까지 증가 할 수 있습니다. 의 더 많은 값을 테스트합니다 RecognitionThreshold. 에서 올리기 1001000sufficies; 어떤 이유로 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하지는 않습니다 . 그 의미는 "와 같은 것을 볼 때마다 내부에있는 것을 불러서 전체를에 바꿉니다 ."fxx^2f[ ... ]xx^2

이 두 가지를 종합하면, gMathematica 의 정의가 양식의 표현을 (g[ ... ])[ ... ]과제의 오른쪽 으로 대체 하도록 지시하는 것을 알 수 있습니다.

Mathematica가 g[m](의 두 번째 줄에서 f) 식을 만나면식이 알고있는 규칙과 일치하지 않으며 식을 그대로 유지합니다. 그런 다음 인수 와 목록 이 있는 Map연산자 와 일치합니다 . ( 접두사 표기법입니다.이 표현식은와 정확히 동일합니다 .) 첫 번째 인수를 두 번째 인수의 각 요소에 적용하여 대체합니다 . 이제 Mathematica는 각 요소가 정의와 일치 하고 대체를 수행함을 확인합니다./@g[m]{i, ImageReflect@i}/@Map[g[m], { ... }]Map{(g[m])[i], (g[m])[ ... ]}g

이런 식으로 우리는 g다른 함수를 반환하는 함수처럼 행동해야합니다. 즉, 우리가 쓴 것과 비슷하게 작동합니다.

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

(이 경우 g[t]를 제외하고 는 자체적으로는으로 평가 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에는 염소를 결정하기위한 내장 기능이 있습니다. 나는 그것에 대해 어떻게 느끼는지 모르겠다.
Robert Fraser

119
Whaaat Oo 내장 이 있습니다 .... 와우 ...
Downgoat

171
당신은 나를 농담하는 염소 ...
corsiKa

27
Mathematica가 "더 염소 같은"이미지를 볼 수있는 경우 +1
QBrute

9
이것은 긍정적으로 우스운 일입니다. +1.
ApproachingDarknessFish

71

자바 스크립트, 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

@ Downgoat p. 점수가 업데이트되었습니다.
user81655

불행히도 이미지를 180 ° 회전하고 세로로 뒤집 으면 실패합니다. 스크린 샷
mr5

@ mr5 Interesting ... 스크린 샷의 이미지가 downgoat 4와 약간 다른가요? 또한 브라우저와 운영 체제간에 약간의 차이가 있습니다. 이 답변의 매개 변수를 사용하면 Chrome과 Firefox (Windows 사용)에 대해 동일한 결과를 얻었습니다.
user81655

63

파이썬, 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 그래서 당신은 그의 대답을 downgoated?
Ave

2
imgur 또는 다른 것으로 파일을 업로드하여 수정하십시오 ^^ 또한 왜 세계에서 bing을 사용 하시겠습니까 ???
Eumel

17
@Eumel Google은 HTTP 요청의 User-Agent가 다른 응용 프로그램이나 스크립트가 아닌 실제 웹 브라우저 (또는 허용되는 것)에 속하는지 확인하기 때문입니다. Bing은이를 확인하지 않고 들어오는 요청을받는 것에 대해 필사적입니다. User-Agent는 추가 코드로 위조 될 수 있으며 코드 골프가 아니기 때문에 중요하지 않습니다.
JordiVilaplana

14
그 표준 허점은 코드 골프 답변을 작게 만들기위한 것입니다. 이것은 코드 골프 도전이 아니기 때문에 허점이 어떻게 적용
되는지 모르겠습니다.

58

자바, 93.9 % 100 %

이것은 이미지의 위쪽과 아래쪽의 행 대비를 결정하여 작동합니다. 이미지의 아래쪽 절반의 대비가 두 가지 이유로 더 크다고 가정합니다.

  • 4 개의 다리는 바닥 부분에 있습니다
  • 상단 부분의 배경은 일반적으로 초점이 맞지 않는 영역이기 때문에 흐려집니다.

인접한 픽셀 값의 차이를 계산하고 차이를 제곱하고 모든 제곱을 합산하여 각 행의 대비를 결정합니다.

최신 정보

두 번째 배치의 일부 이미지로 인해 원래 알고리즘에 문제가 발생했습니다.

upgoat3.jpg

이 이미지는 이전에 무시되었던 투명도를 사용하고있었습니다. 이 문제를 해결할 수있는 여러 가지 방법이 있지만 모든 이미지를 400x400 검정색 배경으로 렌더링하기로 선택했습니다. 다음과 같은 장점이 있습니다.

  • 알파 채널로 이미지 처리
  • 인덱스 및 그레이 스케일 이미지 처리
  • 성능 향상 (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

@ Downgoat 그렇습니다. 점수를 업데이트했습니다 (올바로 인식되는 아바타의 보너스 포인트는 포함되지 않음).
Sleafar

38

파이썬 3, 91.6 %

새로운 테스트 사례로 편집

테스트 할 염소 그림으로 파일 이름을 설정하십시오. 커널을 사용하여 이미지를 위 / 아래 비대칭으로 만듭니다. 소벨 연산자를 시도했지만 더 좋았습니다.

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 좋은 직업! 맥에 PIL을 어떻게 설치
해야하는지 알아야합니다

두 번째 테스트 사례 배치를 추가했습니다.이를 기반으로 답변을 업데이트 할 수 있습니까?
Downgoat

@ Downgoat 님이 방금 마침
Magenta

@Downgoatpip install Pillow
Assaf Lavie

16

Hough Transform이있는 OpenCV, 100 %

내 원래 아이디어는 염소 다리의 수직선을 감지하고 몸과 수평선에 대한 수직 위치를 결정하는 것이 었습니다.

결과적으로 모든 이미지에서지면은 노이즈가 심해 허니 변환에서 많은 캐니 에지 감지 출력과 해당 감지 라인이 만들어집니다. 내 전략은 수평선이 이미지의 상단 또는 하단에 있는지 여부를 결정하는 것이 문제를 해결하기에 충분했습니다.

# 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

다운 염소 1 가장자리 :

다운 염소 1 가장자리

Downgoat1 라인 :

Downgoat1 라인

Upgoat2 모서리와 선 :

Upgoat2 가장자리 Upgoat2 라인

이 방법은 특히 시끄러운 이미지에서도 잘 작동했습니다. 다운 염소 3 가장자리와 선은 다음과 같습니다.

다운 염소 3 가장자리 downgoat3 라인


추가

허프 변환이 캐니 엣지 감지보다 훨씬 잘 작동하기 전에 중간 블러 및 적응 형 가우시안 임계 값이 나타났습니다. 그러나 내 원래 접근 방식의 문제는 즉시 분명합니다. 일부 그림에서 염소의 얼굴뿐만 아니라 눈에 띄는 배경 선이 감지됩니다.

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))

downgoat8는 다음과 같습니다.

downgoat8 thresh downgoat8 가장자리

등고선 (코드 표시 안 됨)은 염소 (척추)의 위쪽 가장자리를 꽤 잘 감지하지만 전체 모양을 얻지 못합니다.

윤곽

추가 연구 : OpenCV에는 Haar-feature 기반 물체 감지 기능 이 있으며 일반적으로 자동차 나 얼굴과 같은 물건에 사용되지만 독특한 모양으로 인해 염소에도 효과가있을 수 있습니다.

2D 기능 인식 이 유망 해 보이지만 (스케일링 및 회전으로 인해 템플릿 일치가 작동하지 않습니다) C ++ 용 OpenCV를 파악하기에는 너무 게으 릅니다.


10

파이썬 3, numpy, scikit, 100 %

이 코드는 단일 파일 이름에 대해 염소 훈련 이미지 분류기를 실행하여 'Upgoat'또는 'Downgoat'을 인쇄합니다. 코드 자체는 python3의 한 줄이며 앞에는 거대한 문자열과 가져 오기 줄이 있습니다. 거대한 문자열은 실제로 염소 훈련 분류기이며 런타임에 선택되지 않고 분류를 위해 입력 이미지가 제공됩니다.

이 분류기는 Randal Olson의 TPOT 시스템과 펜실베이니아 대학의 팀을 사용하여 만들어졌습니다. TPOT는 유전자 프로그래밍을 사용하여 기계 학습 이미지 분류기 파이프 라인을 발전시키는 데 도움이됩니다. 기본적으로 인공 선택을 사용하여 입력 데이터에 가장 적합한 다양한 매개 변수 및 분류 유형을 선택하므로 파이프 라인 설정을 꽤 잘하기 위해 기계 학습에 대해 많이 알 필요가 없습니다. https://github.com/EpistasisLab/tpot . TPOT는 scikit-learn, INRIA 등의 http://scikit-learn.org/stable/에서 실행됩니다.

인터넷에서 찾은 약 100 마리의 염소 이미지를 TPOT에 제공했습니다. 나는 테스트에서 염소와 비교적 비슷하게 보이는 것을 선택했다. 이 TPOT 프로세스의 출력은 기본적으로 scikit-learn ExtraTreesClassifier 객체입니다. 이 이미지 분류기는 내 염소에 대해 훈련 (또는 '맞춤') 된 후 거대한 줄에 절여졌습니다. 문자열에는 분류기 코드뿐만 아니라, 훈련 된 모든 염소 이미지에 대한 훈련의 "인쇄물"이 포함되어 있습니다.

나는 훈련 이미지에 '로그에 염소 서'테스트 이미지를 포함시켜 약간의 속임수를 썼지 만, 일반 염소 필드 이미지에서는 여전히 잘 작동합니다. TPOT을 더 오래 실행시킬수록 더 나은 분류 기가 만들어지는 단점이 있습니다. 그러나 더 나은 분류자는 '더 큰'것처럼 보이며 결국 골프 게임에서 @Downgoat에 의해 주어진 30,000 바이트 제한에 도달합니다. 이 프로그램은 현재 약 27kbyte입니다. 테스트 이미지의 '두 번째 그룹'은 '백업 링크'와 마찬가지로 손상되어 있으므로 어떻게 수행되는지 잘 모르겠습니다. 그것들을 수리해야한다면, 아마도 다시 시작하고 TPOT를 다시 실행하고 많은 새로운 이미지를 공급하고 30k 바이트 미만에서 새로운 분류기를 만들 수 있는지 확인하십시오.

감사

피클 가져 오기, bz2, base64, numpy, sys, skimage.transform, skimage.io
s = '' '
QlpoOTFBWSZTWbH8iTYAp4Z ////////////////////////////////////////////// 4E6fAAPR
OCLRpIfAbvhgIAAAAJCgAG68fDuYNrAwQbsADQAKBIJBITroq0UyRVNGVqljJVSvgAAAAEgAAAAA
AAO7AABugXamjQYyCIABQ6O7LEQ2hRwOdKSFCVuGgF1jBthaAUAAEgKGLVAAAAAKKCVFBIFEFKVE
DQNAaNPUGjTJjU000G1PU0ZAaaGJoyDQaDaQxPRP0oZpNo9NRGaJtRoaYmmyammnqGAjTBNpG1Ga
mT01GRoemTFNnoRNPZCm09pmP9VVVBlIgAAAmgAAExNAaBo0A1MA0ZAADRMCZoAajBNMGjTSntAC
YJgGiYJjU0YNTTCYCYTANABMATKHInox / 7VSqoZMgGQaGRoADQaDTRo00YQaAGgAGQ000yGmjQNG
mQ00DRhNADCNAAGmTIZGgaNGmgMhoZNAZDIIp4EBNACNNEMmhUjTyJ6T0h6k9qnqbTU8NCnqDaTJ
oaabTUaNqG0jIyG0T0ID1BkaGj1ABoMgGgwIxNAGhkGmTCZA0Ghk0DCKUQECYBMmIEyJhlPTU8k9
TGmpP0NNU9t 롬 TaU9PSep6UeIGGSGJppsU9MTKbVPyFPZMU8ET9QmmnppiJp5TT0A1PNSeJknpH
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
5IwHuctF9lda56rrWDJy / 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
SIIujEYQg54EMjYyhJ5RKKM2hqbDJmxkz60YxYmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVYygAwAAAA
AAAAAAAAADGQAFVVVYAAAAAAAAAAAAABVVVQAAAAAAAAAAAAAAAGMYxjGMYxjGAAAAAAAAAAAAKqqqxl
yZAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABVVVVVVVVVVVVVVVVVV
VAAAAAAAAAAAAVVVVaNXYZ9XJsNOhzoPjATZ7gjJHGZqZvMIwUCNiA3ON7mg8lirSKUQUpMTI0ZQ
NxorCSQKMFRGdFjaEZPhGEoxlKUgAAAAAAAAAAAACqqqgAAAAAAAAAAAAAMjNnzZtbNq6 + jLp12r
r2pm17IyPWUke6TzZ7lg4jfIoCcieoRCAEiwesXIqSVnqmaamnS1s + tra2wz6NGfV0Yy5cmXV058
2tp06cYYAAAAAAAAAAAAAAAAAAAAAAAAxjGMYxjGMYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqqqqq
qqqqqqqqqsZcgAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAqqqqqqqqqqqqqqAAAAAAAAAAAAAAxkyZcmTL5X
UABaQRUCkFAEpBFgkAQi / yAIiyQorG8kZN9kMZMAVA1v18dKaO4pB0771qIqBiQVUIgVU / 3hAHaM
ggEApEkkXUCueVjqIqwv0JBQVdUQaqXTh01SUQosK + NiU2qmwMHABALMSQ + BUXW + 7Xr09DlfqrdX
/ 939Xyc9YbJ / GjfTHd3mflYe8dzKSXup + r / HbwMZ8arVvHPdveWSm6FplrPLVmr2S843G4vE5O65
Luf + 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 + / Vl6qqqvd5iqqqqqrhaqqqqqqqqqqqqqqqqqquIqqqqqqqqyePyc1k5OTkfLyMjIyMfNY
/ KY + Pj / au3bt27dzdy5cuXLlzBuXLly5z9y5cuXLmguXLly5tOh2nRbTabLF / Nh7PF6XF0eLi4uL
i4mJiYmJiYlvY4eHsuuw7du3bt27du3bt2 + 3t27du3b4HA4HA4HA4HAu9rd3d3tLu7u7u7u7v2N7
7G93u93v1 + rB5b7eYRBmhGtRBsKy / GX7nOB1 / E3 / qXrb / 3FEEsgr3NOugQYgYIUoKUpDoMnMf9JD
lIjzOcRB8V0nUZ / J2IjPhEeewNb0JbaLYXfo9aPzTK2tiN5ALOEUiEbNlrUDRlB1MS + eEEA + BDJZ
+ PbCQi4er6zV6K2iiCwOAQHKAQEIQIgsK8HQmk + 3XIg4AbHDyyj2C7CQc / V3ix6TAb7qDRb / pOt1
ebs0bSBiBYgWQEG0bTBQpV + hi7qnVA6OEHS20 / p / 23o0fEmnxQ1qhXQkQrW1g1sHjQFrLvb + iAWn
lK9nsvYQQqUWDrj30rLLFl85s4pl / CToEB2gAIQS7ZrwaSB08E27237snaWSIO7jXauo4q + b4OeE
KpUKxq14UISbjbs2RBAPUU1ezYCbpVcJlh3K9CL7 + BIebaJl1OUvpTI + aCSVpzU + Il8r4GQDpJoG
gGgR2en5fPQIPnu4x7XtkzByrR1QKTpsdMNCQYt0AaIlc2aEEAs + qCTtZfBwYICmu4fpDGr2Hjae
psCC2AKD6apD39bTAGwy + BZPQCAWOGWUaOFSbfCbMAyqoOAQQ6SDoATyAMWOZrG0hbHBBALXsyTC
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
mggioJIIKaihqQIgCBoq1EiKJoimJCBiaiKiIZGoCAlsO4Q4pEERVJBBCI / 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 + Wdp5FnlHAGiMrrzB4ZyE2tsGErymPlkGDldc1J56XsL3uXUGN
4DjdYteEsK6aeWGMHQvhmLq81RyULQkPDuY7gaQmBYkohgb3TU8TrR5gannWpg + WTydjeeD3uUNA
2z63a3xxMLTHLNaIGAYkiPGHTIkiuaTyjnXCZcOvY7rJsRK / kyXWF1YxE63khaonFdmIOIZCBo1S
8dCHtB / bqoGF12thHvgxOedj4ypXY29TNWidorby8bsa3O2fAMszfcuZdsYrMudt7PnuznKXFGfC
NAERIRIXFE0ZCnSD3VOodpzSGr3hO1zz2dgHNH8x1rpXbTOd4vwiltm22MIboTvvrrnaMgO2
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
LoaV2y1gWvwu63hPC6q4moW6XZ1nyryWuB7wZLgy3EDoXaaJYHOuxlwvcm6utwbo9q8DXKOG22mG
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 + lIAD9mt / zGlUfQ + JjFIiPvA + ZQBp
NWASGpwEHoHCMCERNb2spMiGGdf5lPB2LP76yDuSA / RcQA3CtAvgCE0AXFBfnEx / JLzDNpVN + Oeh
RDKQomGH8ZM0NuzZmn79Hfc4YPup93UHasgv4QggaJHOn1EwiDfAQG9PJ / HYVl1QopWPXywz / U9S
rhfVhWVmAAfiHRe7oEgno + nUBx0EdXoiDg64EG / DBBsgg9aCDM6Oqmz0QfL8dEG6FBrs0iDwuvBB
7bTyRdep5XiYJve8Jn9x2GM6qbeJfw0cfXRFa2WDuk8 / cby9fjROB5FpqFykYm1PLvHxr9qmCrlQ
3MSgOa1zfHbyfH4DKpqUvbDard1K03Worpp08ulIiD8kBJ + xixlpbofFrr5GvR995mAmIg7LlEQa
3spgCDg7 + CD + JEG9DhQQdgIPiwQfIQIPnbrfHZznOc5znOc5znOcg5ByDkHIOQcg5ByDkHIOQcg5
ByDkHIOQcg5ByDkHIOQcg5ByDKpKpKpKpKpogBBm6P8NdyPJefd6HrvsfT2 / rcLO5bK + Fd / 6 + LKK
W7rtf77ynFU + GBH + cLn4VHj6WRcDVAg1NyoDLWqA / xzf0dnh9zw9DlqpVTZe1pvE의 KpzXN8vf85
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
hJemYWGWffGSSokFQhNBj6gfMGpzy9QO7zQ5a8CFA98Mv0CgfzfuHIKdPp6gAPD8ABDIPxPP997
00 / 1 + 7Vf0M + oxq9jy5ThAnvnJmTj + 2OYOg5CZyJE8f + 3uXucXvDP9T + SDeO + ISnbL4bpVUABUYVL
7gXNX / LoTNp / Ym9nFudlNVYiRURymZRUkQUSLMrFBnwVWIkVPTq / 8u5U7jm / + IbMP2rfw3WSe55f
07XWWsziJFRHqfxqHNvwzZRVf3qVwc5C51vnWzfqnmasiQUz + G / fJRxMwp65aQcziraVQVB51ABt
gNsB7zG2DaA2gNsBtoG1BtQehOlzvA22DsB7TaByDxgdwHdyDsB1BgdQZoNUDbjTAzwZwM8GQG8A
zwaIN4Bmg6g7AcA4B0B1B0B0B2gdQcg5BwDug6g4B0B0BgdA25O0tgO3vA7gNEGgDRBkBogzwZ4N
MDNBmg + zPBlByDqDsB0B0B2wdNQdAdAcA7oPY7QOQfqNgOwGB2G9IbAd8HdB2wdgO0DgGeDOBxBT
g1IMp86u6Alr2mBsKcGoBlBpzpeXoGzgiImdM8ryUktMDWAzweZw + DqgayrvFO1YNiDUA7QPJ0Bg
yDv8AM8aHdnQHV2gddbaBtNAdm1zITAPADug7oOwHcBwDtA7AeODwA6g6g7AcA4B0B1B0B0B2gdQ
cg5BwDuA6g4B0B0BgdAdAdwHYDmyeDOBngyA0wM8GiDTA + / OBnAzwZAcA6g7AdAdAdwHUHIOQcA7
wOoAdAdAYHQHQHeB2A7AdQdgOAd0HYD6HcB3gdgOwHaBwDgHQHYDoDoDtg6g5ByDgHdB1BwDoDo
DA6A6A8xTqUKCmvoqUFKKkilQpRUnqU6k1SapOUkUkUmKTVNpNUmqUVJyl / mKT5qminEU21MKaqd
tqphT + HYG / FV2rh21OMpUKUylBSipIpOUnKU6F9B / UDkrP6SW8gOEGEPQ6gHrR4h7AexQYQd3VOQ
Q5kCey9eYBCoBYBqCcoNtZ7 + lYPlQ5EZ0fwSB / St4j013Mj796pDwCEQBm0CAgEgpnKuxT6CMeKs
HFM8HQ8gQxELGRIaSywjHJLQubX1C7AyKXGirdk5H946pfTw / 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
IzZtYzZutjNm1jMDkGByGtFc9ZAdQYHUGB2bNSpoyA6gwOoMDl0JIwA6AwOgMDnQoiKwA6AwOgMD
nSCrY5AdQYHUGB1dZijADoDA6AwOmjVMYVNFIUmKQpLMidOlIlZgpOU + XtLcv + Ro9X10bv9O23QX
7SXom0IIf3783F4pv39Hd5mApYbSLiSSEgXwO2Bh / X9Klcmc4s7ur8hIODmidLHN8l2Dzm17p770
nm / v / ZeD8VVVfAxiMRiMRiMRiMSOAYBwDAOAYBwDAOAYBwDAOAYBwDAOAYBwDAOAYBwDAOAYBwDC
mFIUwpEiHp5hzUO9MUV + evADDkP70VrEkDS4YAtctpD1 / JLDtsPG0gb / UlKiuB6Lor3bc4AayABK
2H6AIMv5AEGw2nTf19GskBAMPpNPm79DmTgiArc9l7a8F5Pn0kKRAg6tAEEgJwcU0AofWwmlBCog
aYsShhH0eTViKn + EVEcUjVghr6SMacICSGQegFn + errwXxHkzS2eAFY + kDmfhyVYaAHfOIWON
2vIUbiBJz4GGp7J7ZmrAl + 8znekOADQSzQMmnd2djdZ2M42gxyWkpoS0Z / vz6iraIOyH / wgFImr9
HwOFslabdTMuJGdceuFXIz3k / HiqW5CEEzz + / 68Cx84flyhY57tPmrL3W6XTk + HBMuD4dNfyseDx
IEUgAJiBFRbZ6Ya4GTBJCu3aIgUNlzPNZMwD7e3doqIb0FU5NKLU36M1UcrY9Zasd000667DsA9O
2fezKtc0ACZ96QKVVd38AfCG + 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
27ALs MvbKdiYk758z1fhZ2tpE582oakBCDQpYLb2f9aaIVde2s07g / YmQ7K / 4hMXjjv / vydgAAHQ
so9Qndo / gHfAMfN4bq559ZJvb9uXqspwG9t85m88P5 + Rr4aOSdOAgVlikVHyd2Ti3HmKBi / MqaDV
sL1wnAE / ugR4gKqO / JC8W22Jze5spAZvgZQABAHIQmjKk5GtKIji7fxd1TQdaKuPNiFUFWJS65ED
L8z9yBQjcAwxBBYEEAsH4A2Pyua7maKaRlLL19G3fKeTethH7eWqznAFAdIQSJG4csaHOYnnS / OX
OOHLz8lZFKrC0uU3JBd6GNU6sAhYHhEwgm3AHBDEV3azVaxnDsmWxXKeZ66gYHfVOQvAAfnmKdAA
IIEprt8vV1H5c5vaVWRPLOCM3l6atqSeFYOWBegAvIdAGgntK2Uj5vwFD4VlJKRlVC0J
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 + deSU7Mn1VyW9ymSQKfkeYaeSFbQQKvLHS8ezgjOE31LchHRplOT
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
휴 보트 + 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 + icyyqL4qX9xHgAA + 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 이미지 검색, Google 이미지 검색 등

24x12 픽셀의 훈련 데이터


훈련 데이터를 게시 할 수 있습니까?
qwr

내가 사용한 원래의 정확한 이미지 중 일부는 저작권이므로 모두 게시 할 수 없지만 24x12 시스템에서 사용 된 크기로 많은 이미지를 축소하고 위의 단일 몽타주 이미지로 게시했습니다. 공정 사용 '.
밝게

6

임의의 숲이있는 사이 킷 학습, 100 %

시도되고 진실 된 접근 방식은 convnet이지만 임의 포리스트 는 기본적으로 매우 잘 수행 할 수 있습니다 (조정할 매개 변수가 거의 없음). 여기에서는 이미지 분류 작업의 몇 가지 일반적인 기술을 보여줍니다.

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 교육 데이터를 게시하려고했지만 모든 사진이있는 폴더는 죽은 하드 드라이브에있었습니다. 누군가 야심 찬 사람이라면 구글 이미지 검색을 사용하여 내가 사용한 사진을 찾을 수 있습니다.
qwr

멋지다. 이미지를 많이 다운로드했지만 "깨끗한"이미지를 정렬하는 데 많은 시간이 걸렸습니다. 정렬하는 데 많은 시간을 소비하지 않고도 더 '더러운'이미지를 기반으로 훈련하는 방법을 보는 것이 흥미 롭습니다.
밝은 돈

@donbright 나는 더 많은 훈련 데이터와 다양성이 더 좋다고 생각합니다. "깨끗한"및 "더러운"의 경우 데이터 확대를 사용하여 "더 많은 데이터"를 만들 수 있습니다.
qwr
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.