Quantcast
Channel: プログラム の個人的なメモ
Viewing all 860 articles
Browse latest View live

【トラブル】【Oracle】エラー「ORA-01799: 列は副問合せに対して外部結合されません。」が表示される

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37767007.html
で、以下の「エラーが発生したSQL」のようなSQLを実行したら、
エラー『ORA-01799: 列は副問合せに対して外部結合されません。』が表示された

■ エラー内容

SQL   : ORA-01799: 列は副問合せに対して外部結合されません。

エラーが発生したSQL


SELECT
 S2.YEAR AS PREV_YEAR,
 S1.YEAR AS YEAR,
 S2.SALE AS PREV_SALE,
 S1.SALE AS SALE,
 S1.SALE - S2.SALE  AS DIFF,
 CASE WHEN S1.SALE = S2.SALE THEN '→'
      WHEN S1.SALE > S2.SALE THEN '↑'
      WHEN S1.SALE < S2.SALE THEN '↓'
 ELSE '-' END AS UP_OR_DOWN
FROM
 SALES S1
LEFT OUTER JOIN
 SALES S2
ON
 S2.YEAR = (SELECT MAX(YEAR)
                    FROM SALES S3
                   WHERE S1.YEAR > S3.YEAR)
 ORDER BY YEAR

発生環境

 * OS : Windows10
 * DB : Oracle 11g

■ 原因

Oracle は、 外部結合するテーブルの結合条件に副問合せが使えない

■ 解決案

 * 「NOT EXISTS」を使う

SQL

SELECT
 S1.YEAR AS YEAR,
 CASE WHEN S1.SALE = S2.SALE THEN '→'
      WHEN S1.SALE > S2.SALE THEN '↑'
      WHEN S1.SALE < S2.SALE THEN '↓'
 ELSE '-' END AS UP_OR_DOWN,
 S1.SALE AS SALE,
 S2.SALE AS PREVIOUS_SALE,
 S1.SALE - S2.SALE AS DIFF
FROM
 SALES S1
LEFT OUTER JOIN
 SALES S2
ON
 S2.YEAR < S1.YEAR
 AND NOT EXISTS(SELECT 1 FROM SALES S3
  WHERE S3.YEAR > S2.YEAR AND S3.YEAR < S1.YEAR)
ORDER BY YEAR;


関連記事

相関サブクエリ / 自己相関サブクエリ のサンプル

https://blogs.yahoo.co.jp/dk521123/37767007.html

【Java】DBアクセスライブラリ [5] ~ Doma ~

$
0
0

■ Doma

 * Doma : Domain Oriented MApping framework (ドメイン指向マッピングフレームワーク)
 * 読み方は、「ドマ」
 * Javaの和製フレームワーク Seasar の O/Rマッパー S2Dao の後継として、開発。
  => 現在は、Seasarプロジェクトとは、独立。
http://www.seasar.org/

ライセンス

 * Apache License, Version 2.0
  => 商用可能

バージョン

Doma
 * Java 6 でコンパイルされ、 Java 6、 Java 7、 Java 8 上で動作
Doma2
 * Java 8 以上。Java 7 以前では対応せず
Doma3
 * Java 11。

# Doma3 まであるのは、知らなかった... 開発中?
https://doma.readthedocs.io/ja/doma-3/

■ 特徴 / 利点

 * SQLを外部ファイルに書ける (2 Way SQL)
 * コンパイル時にできるだけチェックし、ミスを事前に防いでくれる
 * 依存ライブラリがない



関連記事

【Java】DBアクセスライブラリ [0] ~ 目次 ~

https://blogs.yahoo.co.jp/dk521123/37773005.html

【Java】DBアクセスライブラリ [0] ~ 目次 ~

$
0
0

■ Java の DBアクセスライブラリ

【A】 JPA以外

[A-1] EBean
https://blogs.yahoo.co.jp/dk521123/36044963.html
[A-2] Apache Commons DbUtils
https://blogs.yahoo.co.jp/dk521123/34079202.html
[A-3] Persist
https://blogs.yahoo.co.jp/dk521123/36050559.html
[A-4] Iciql
https://blogs.yahoo.co.jp/dk521123/36053260.html
[A-5] Doma
https://blogs.yahoo.co.jp/dk521123/37773041.html
[A-6] ORMLite
[A-7] GreenDAO
 * Android ではよく使われているみたい

JPA準拠

[B-1] Hibernate
[B-2] EclipseLink

■ JPA (Java Persistence API)

 * 永続化管理のためのAPI仕様
  => 実装は含まない

【Java】Pluggable Annotation Processing API

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37773041.html
で、「Pluggable Annotation Processing API」を使っているとのことだったので、調べてみた。

■ Pluggable Annotation Processing API

 * コンパイル時にアノテーションを読み込んでくれる機能
  => アノテーションについては、以下の関連記事を参照のこと
https://blogs.yahoo.co.jp/dk521123/32740125.html
 * Java1.6から追加された機能
 * Java1.5から追加されたAnnotation Processing Tool (apt)とは別物

■ サンプル

【例1】Hello World

DemoAnnotationProcessor.java
package com.sample.annotation;

import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;

public class DemoAnnotationProcessor extends AbstractProcessor {
  private int round = 1;

  @Override
  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {
    System.out.println("Round : " + (this.round++));
    annotations.forEach(System.out::println);
    return true;
  }

  @Override
  public SourceVersion getSupportedSourceVersion() {
    return SourceVersion.RELEASE_8;
  }
}
DemoClass.java
package com.sample.annotation;

public class DemoClass {
  @Deprecated
  public void deprecatedMethod() {
  }

  @Override
  public String toString() {
    return "demo";
  }
}
コマンド実行
cd C:\eclipse\workspace\DemoProject\src\main\java

# コンパイル
javac com/sample/annotation/DemoAnnotationProcessor.java

dir 

javac -processor com.sample.annotation.DemoAnnotationProcessor com/sample/annotation/DemoClass.java


関連記事

アノテーション ~ Annotation ~

https://blogs.yahoo.co.jp/dk521123/32740125.html

Antビルドにより、CSVファイルからEnumクラスを自動生成する

https://blogs.yahoo.co.jp/dk521123/33914928.html

USDM ~ 要件定義 / 仕様記述手法 ~

$
0
0

■ はじめに

 要件定義や仕様書で USDM ってのがでてきたのでメモ。
シンプルで、表で記述するから要件定義の漏れが少なくて、今後のプロジェクトにも役に立ちそう。

■ USDM

 * USDM : Universal Specification Describing Manner
  => 日本語で直訳すると、「普遍的仕様記述法」?

 * 要求(上位要求、下位要求)と仕様を階層構造で表現する

【トラブル】【Oracle】Oracle の トラブルシューティング

$
0
0

■ ORA-00972: 識別子が長すぎます

原因

 * テーブル名が30文字を超えていたため

参考文献

https://kb.tableau.com/articles/issue/error-ora-00972?lang=ja-jp

■ ORA-01799: 列は副問合せに対して外部結合されません。

 * 以下の関連記事を参照のこと
エラー「ORA-01799: 列は副問合せに対して外部結合されません。」が表示される
https://blogs.yahoo.co.jp/dk521123/37771488.html

関連記事

アンインストール途中でエラー(エラーコード:OUI-10020)

https://blogs.yahoo.co.jp/dk521123/19571197.html

【SQL】 SQL アンチパターン ~ Entity-Attribute-Value(EAV エンティティ・アトリビュート・バリュー) ~

【JUnit】ランダムデータ生成によるテスト ~ jPopulator / junit-quickcheck ~


【Unity】 Unity ~ 入門編 ~

ビッグエンディアン / リトルエンディアン

$
0
0

■ エンディアン

 * バイトオーダー(byte order)
 * データをバイト単位で見たときの並べ方

■ ビッグエンディアン (big endian)

 * 最上位のバイトから下位に向けて順に記録・伝送する方式

■ リトルエンディアン (little endian)


参考文献

【Java】Javaで標高データを扱う

$
0
0

■ はじめに

 * Javaで標高データを扱う
 * 今回扱うデータは、「SRTM」で、ビッグエンディアンの2バイト整数として格納されている
ビッグエンディアン については、以下の関連記事を参照のこと
https://blogs.yahoo.co.jp/dk521123/37795867.html

標高データ

標高 : elevation
【1】 SRTM (Shuttle Radar Topography Mission; スペースシャトル地形データ)
  1-1) SRTM-1
   => 1秒メッシュ(約30m)の分割地形データ
  1-2) SRTM-3
   => 3秒メッシュ(約90m)の分割地形データ

■ SRTM

 * SRTM DEMフォーマット(.hgt)
 * ファイル名は、「北緯東経.hgt」で構成
  => 例: N35E139.hgt = 北緯35度、東経139度
 * 各標高値 : ビッグエンディアンの2バイト整数。単位は、メートル。

ダウンロード先

http://dds.cr.usgs.gov/srtm/version2_1/SRTM3/

参考文献

http://kamoland.com/wiki/wiki.cgi?SRTM3%A5%C7%A1%BC%A5%BF%A4%AB%A4%E9%C9%B8%B9%E2%A4%F2%C6%C9%A4%E0
http://www.gis-okinawa.jp/grid/SRTM3/
JAXA
http://iss.jaxa.jp/shuttle/flight/sts99/mis_srtm.html

関連記事

ビッグエンディアン / リトルエンディアン

https://blogs.yahoo.co.jp/dk521123/37795867.html

【Java】Doma ~ 初期環境構築 / コード生成 ~

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37773041.html
の続き。

Oracle DB / Doma2(Spring等のフレームワークなし) / Gradle のサンプルって
意外となくて、結構ハマった。

■ 実行環境

 * OS : Windows10
 * Java : JDK1.8 
 * Eclipse Java EE IDE for Web Developers (Version: 2018-09 (4.9.0))
 * DB : Oracle 11g

■ 初期環境構築

事前準備 / 前提条件

 * Oracle ID を事前に取得しておく
  => 今回、例として、ID「demo@sample.com」、Password「password」 とする
 * Gradleプロジェクトで作成

テストデータ

 * 以下の関連記事のものを使用
https://blogs.yahoo.co.jp/dk521123/37756250.html

手順

[1] Eclipse上のプロジェクト内の「build.gradle」を以下を参考に修正する
[2] プロジェクト内を右クリックし、[Gradle]-[Reflash Gradle Project]で、
    依存するライブラリをダウンロードする
build.gradle
// Apply the java-library plugin to add support for Java Library
apply plugin: 'java-library'

// JavaクラスとSQLファイルの出力先ディレクトリを同じにする
processResources.destinationDir = compileJava.destinationDir
// SQLファイルを出力先ディレクトリにコピーするために依存関係を逆転する
compileJava.dependsOn processResources

configurations {
    domaGenRuntime
}

// In this section you declare where to find the dependencies of your project
repositories {
    // Use jcenter for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
    mavenCentral()
    maven {url 'https://oss.sonatype.org/content/repositories/snapshots/'}
    maven {
      url "https://www.oracle.com/content/secure/maven/content"
      credentials {
        username 'demo@sample.com'
        password 'password'
      }
    }
}

dependencies {
    domaGenRuntime 'org.seasar.doma:doma-gen:2.19.3'
    domaGenRuntime 'com.oracle:ojdbc6:11.2.0.3'
        
    compile group: 'com.oracle', name: 'ojdbc6', version: '11.2.0.3'
    
    domaGenRuntime 'org.seasar.doma:doma-gen:2.19.3'
    compile group: 'org.seasar.doma', name: 'doma', version: '2.19.3'
    compile group: 'org.seasar.doma', name: 'doma-gen', version: '2.19.3'
    compile group: 'org.freemarker', name: 'freemarker', version: '2.3.28'
    
    // Use JUnit test framework
    testImplementation 'junit:junit:4.12'
}

// Javaコード生成する(★後述「■ コード生成」で使う★)
task gen {
    group = 'doma'
    description = 'Generate Java codes'
    doLast {
        ant.taskdef(resource: 'domagentask.properties',
            classpath: configurations.domaGenRuntime.asPath)
        ant.gen(
            url: 'jdbc:oracle:thin:@localhost:1521:xe', user: 'TEST_USER', password: 'password',
            templatePrimaryDir: 'templates') {

            entityConfig(packageName: 'com.sample.db.doma2')
            daoConfig(packageName: 'com.sample.db.doma2', configClassName: 'com.sample.db.doma2.DbConfig')
            sqlConfig()
        }
    }
}

■ コード生成

 * コード生成には、「Doma-Gen」を使用する

Doma-Gen

 * AntとFreeMarkerを使用したDoma2 のための コード生成ツール
目的
 * 以下のJavaコード生成
  + エンティティクラス
  + エンティティリスナークラス
  + Daoインタフェース
  + SQLをテストするためのJavaテストコード
 * 以下の生成
  + SQLのコード
テンプレートファイル
https://github.com/domaframework/doma-gen/tree/master/src/main/resources/org/seasar/doma/extension/gen/template

手順

前提条件:上記の「■ 初期環境構築」が行われていること
[1] 「org.seasar.doma.jdbc.Config」を継承したDB設定クラスを作成する(以下の「」を参照のこと)
[2] プロジェクト内を右クリックし、[Run]-[Run Configuration]-[Gradle Project]で、
   「New lunch Project」を選択
[3] 「Gradle Task」タブの「Gradle Tasks:」欄に『gen』を入力し、「Run」ボタン押下し、
    コード生成を実行する
 => 「Person.java」「PersonDao.java」「PersonListener.java」が作成される
DbConfig.java
package com.sample.db.doma2;

import javax.sql.DataSource;

import org.seasar.doma.SingletonConfig;
import org.seasar.doma.jdbc.Config;
import org.seasar.doma.jdbc.dialect.Dialect;
import org.seasar.doma.jdbc.dialect.OracleDialect;
import org.seasar.doma.jdbc.tx.LocalTransactionDataSource;

@SingletonConfig
public class DbConfig implements Config {
  private static final DbConfig CONFIG = new DbConfig();
  private final Dialect dialect;
  private final LocalTransactionDataSource localTransactionDataSource;

  private DbConfig() {
    dialect = new OracleDialect();
    DataSource dataSource = new LocalTransactionDataSource("jdbc:oracle:thin:@localhost:1521:xe", "TEST_USER",
        "password");
    localTransactionDataSource = new LocalTransactionDataSource(dataSource);
  }

  @Override
  public DataSource getDataSource() {
    return localTransactionDataSource;
  }

  @Override
  public Dialect getDialect() {
    return dialect;
  }

  // !! 重要 !! シングルトンを返すメソッド名は「singleton()」と決められている
  public static DbConfig singleton() {
    return CONFIG;
  }
}
Person.java (自動生成)
package com.sample.db.doma2;

import org.seasar.doma.Column;
import org.seasar.doma.Entity;
import org.seasar.doma.Id;
import org.seasar.doma.Table;

/**
 */
@Entity(listener = PersonListener.class)
@Table(name = "PERSON")
public class Person {

    /** */
    @Id
    @Column(name = "ID")
    String id;

    /** */
    @Column(name = "NAME")
    String name;

    /** 
     * Returns the id.
     * 
     * @return the id
     */
    public String getId() {
        return id;
    }

    /** 
     * Sets the id.
     * 
     * @param id the id
     */
    public void setId(String id) {
        this.id = id;
    }

    /** 
     * Returns the name.
     * 
     * @return the name
     */
    public String getName() {
        return name;
    }

    /** 
     * Sets the name.
     * 
     * @param name the name
     */
    public void setName(String name) {
        this.name = name;
    }
}
PersonDao.java (自動生成)
package com.sample.db.doma2;

import org.seasar.doma.Dao;
import org.seasar.doma.Delete;
import org.seasar.doma.Insert;
import org.seasar.doma.Select;
import org.seasar.doma.Update;

/**
 */
@Dao(config = DbConfig.class)
public interface PersonDao {

    /**
     * @param id
     * @return the Person entity
     */
    @Select
    Person selectById(String id);

    /**
     * @param entity
     * @return affected rows
     */
    @Insert
    int insert(Person entity);

    /**
     * @param entity
     * @return affected rows
     */
    @Update
    int update(Person entity);

    /**
     * @param entity
     * @return affected rows
     */
    @Delete
    int delete(Person entity);
}
PersonListener.java (自動生成)
package com.sample.db.doma2;

import org.seasar.doma.jdbc.entity.EntityListener;
import org.seasar.doma.jdbc.entity.PostDeleteContext;
import org.seasar.doma.jdbc.entity.PostInsertContext;
import org.seasar.doma.jdbc.entity.PostUpdateContext;
import org.seasar.doma.jdbc.entity.PreDeleteContext;
import org.seasar.doma.jdbc.entity.PreInsertContext;
import org.seasar.doma.jdbc.entity.PreUpdateContext;

/**
 * 
 */
public class PersonListener implements EntityListener<Person> {

    @Override
    public void preInsert(Person entity, PreInsertContext<Person> context) {
    }

    @Override
    public void preUpdate(Person entity, PreUpdateContext<Person> context) {
    }

    @Override
    public void preDelete(Person entity, PreDeleteContext<Person> context) {
    }

    @Override
    public void postInsert(Person entity, PostInsertContext<Person> context) {
    }

    @Override
    public void postUpdate(Person entity, PostUpdateContext<Person> context) {
    }

    @Override
    public void postDelete(Person entity, PostDeleteContext<Person> context) {
    }
}


関連記事

DBアクセスライブラリ [5] ~ Doma ~

https://blogs.yahoo.co.jp/dk521123/37773041.html

【JS】画像比較スライダー

$
0
0

■ はじめに

 * 2つの画像の違いを見比べる際に使用する画像比較スライダーについて扱う

■ cocoen

 * jQuery不要
 * 簡単に設定可能(以下の「設定」を参照)

公式サイト

https://github.com/koenoe/cocoen

ライセンス

 * MIT
https://github.com/koenoe/cocoen

デモ

https://koenromers.com/cocoen/demo.html

設定

 * 以下のサイトからダウンロードする
https://github.com/koenoe/cocoen/releases
サンプル
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Cocoen Demo</title>
<!-- Step1 : CSS をインポートする -->
<link rel="stylesheet" href="css/cocoen.min.css" />
</head>
<body>
<!-- Step2 : 2つの画像を配置 -->
<div class="cocoen">
  <img src="img/before.jpg" alt="">
  <img src="img/after.jpg" alt="">
</div>
<!-- Step3 : JavaScript をインポートする -->
<script src="js/cocoen.min.js"></script>
<!-- Step4 : JavaScriptで初期化 -->
<script>
  document.addEventListener('DOMContentLoaded', function(){
    new Cocoen();
  });
</script>
</body>
</html>

■ jQuery CompareWYW

公式サイト

https://code.google.com/archive/p/jquery-comparewyw/

ライセンス

 * GNU GPL v2

設定

 * 以下のサイトからダウンロードする
https://code.google.com/archive/p/jquery-comparewyw/downloads
サンプル
<html>
<head>
<title>Demo</title>
<link type="text/css" rel="stylesheet" href="jquery.comparewyw.css" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js"></script>
<script type="text/javascript" src="jquery.comparewyw.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
  $('.images').compareWYW({
    event:'drag'
  });
});
</script>
</head>
<body>
<div class="images">
  <img src="http://farm3.static.flickr.com/2345/2380902254_73e2acc497.jpg" width="500" height="333" alt="" />
  <img src="http://farm5.static.flickr.com/4007/4548657637_155a212bd9.jpg" width="500" height="332" alt="" />
</div>
</body>
</html>

■ Image Comparison Slider

公式サイト

https://codyhouse.co/gem/css-jquery-image-comparison-slider/

ライセンス

 * BSD-3-Clause license

デモ

https://codyhouse.co/demo/image-comparison-slider/index.html


関連記事

ライセンスについて

https://blogs.yahoo.co.jp/dk521123/35506016.html

【JS】差分画像を生成するには...

$
0
0

■ はじめに

https://blogs.yahoo.co.jp/dk521123/37801875.html
を調べてる時に、差分画像を生成するライブラリを見つけたのでメモ。
https://blog.htmlhifive.com/2017/10/24/javascript-image-comparison-library/

■ 差分画像を生成する

 * js-imagediff を使う
 * reg-cli を使う
 * Resemble.js を使う
 * ImageMagic を使う

etc...





関連記事

画像比較スライダー

https://blogs.yahoo.co.jp/dk521123/37801875.html

ライセンスについて

https://blogs.yahoo.co.jp/dk521123/35506016.html

【jQuery】スクロール連動 ~ scrollTop / scrollLeft ~

$
0
0

■ はじめに

 スクロール連動について、調べたところ、
jQuery で簡単にできるっぽいのでメモ。

■ サンプル

<!DOCTYPE html>
<html lang="jp">
<head>
<meta charset="UTF-8" />
<title>Demo</title>
</head>
<body>
<div id="upper" style="width:100px; height:100px; overflow:auto; border-style:solid">
  <div>123456789012345678901234567890123456789012345678901234567890</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11</div>
  <div>12</div>
  <div>13</div>
  <div>14</div>
  <div>15</div>
</div>
<div id="lower" style="width:100px; height:100px; overflow:auto; border-style:solid">
  <div>123456789012345678901234567890123456789012345678901234567890</div>
  <div>2</div>
  <div>3</div>
  <div>4</div>
  <div>5</div>
  <div>6</div>
  <div>7</div>
  <div>8</div>
  <div>9</div>
  <div>10</div>
  <div>11</div>
  <div>12</div>
  <div>13</div>
  <div>14</div>
  <div>15</div>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
<script>
  var upperDiv = $('#upper');
  var lowerDiv = $('#lower');

  upperDiv.scroll(function() {
    console.log("Enter upperDiv");
    lowerDiv.scrollTop(upperDiv.scrollTop());
    lowerDiv.scrollLeft(upperDiv.scrollLeft());
  });
  
  lowerDiv.scroll(function() {
    console.log("Enter lowerDiv");
    upperDiv.scrollTop(lowerDiv.scrollTop());
    upperDiv.scrollLeft(lowerDiv.scrollLeft());
  });
</script>
</body>
</html>


【JS】 OpenLayers ~ 入門編 ~

$
0
0

■ OpenLayers

 * 地図表示するJavaScriptライブラリ

ライセンス

 * 2-Clause BSD
https://openlayers.org/en/latest/doc/


■ サンプル

<!DOCTYPE html>
<html lang="jp">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.2.0/build/ol.js"></script>
<title>OpenLayers Hello World</title>
</head>
<body>
<div id="map"></div>
<script type="text/javascript">
window.onload = function(){
    var map = createMap();    
}

function createMap() {
    return new ol.Map({
        layers: [
            new ol.layer.Tile({
                source: new ol.source.OSM()
            })
        ],
        target: 'map',
        controls: ol.control.defaults({
            attributionOptions: {
                collapsible: false
            }
        }),
        view: new ol.View({
            center: [0, 0],
            zoom: 2
        })
    });
}
</script>
</body>
</html>

【機械学習】機械学習に関する覚書

$
0
0

■ 機械学習を導入する前に...

 * 解決したいビジネス問題から始める
  => 機械学習で何をするかではなく、何らかの問題がありその解決案として機械学習を用いるであればOK
  => 別に機械学習を使用せずに解決できるのであれば、そちらで対応すべき

■ 機械学習のフロー

 +-------------+
 |    Start    |
 +-------------+
        |
 +-------------+
 |             |
 |   Models    |
 |             |
 +-------------+
 |             |
 |  Training   |
 |             |
 +-------------+
 |             |
 | Prediction  |
 |             |
 +-------------+
        |
 +-------------+
 |     END     |
 +-------------+

■ 過学習(over-fitting)

 * モデルが「訓練データさえ正解になればいい」と状態になってしまうことで
   未知のデータ(訓練データに含まれない,モデルが知らないデータ)に対する結果が
   デタラメになりがちになる

参考文献

http://gihyo.jp/dev/serial/01/machine-learning/0009?page=2
http://gihyo.jp/dev/serial/01/machine-learning/0021

【トラブル】【AWS】CloudWatch Logs の トラブルシュート

$
0
0

【1】 CloudWatch Logsにアップされない

 日付付きのログファイル名でワイルドカード「*」を使用した際に、
ロググループ名にも「log_group_name=Sample-/var/log/system.*.log」のように指定したら
CloudWatch Logsにアップされなかった。

なお、ワイルドカード「*」を使用しなかった時は、CloudWatch Logs画面で確認できた。

原因

 * ロググループ名「log_group_name」には、「*」が名前として使用できない
  => 詳細は、以下「ロググループ名「log_group_name」の制約」を参照
【公式サイトより】ロググループ名「log_group_name」の制約
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/AgentReference.html
より、抜粋

 * 1~512 文字で指定
 * a~z、A~Z、0~9、"_" (アンダーバー)、"-" (ハイフン)、"/" (スラッシュ) および "." (ピリオド)

関連記事

【AWS】CloudWatch Logs に関する あれこれ

https://blogs.yahoo.co.jp/dk521123/37519819.html

【AWS】EC2内のログを CloudWatch Logs で管理する

https://blogs.yahoo.co.jp/dk521123/37405613.html

【Java】二値画像の細線化

$
0
0

■ サンプル

https://blogs.yahoo.co.jp/dk521123/37815897.html
で、細線化を勉強した時に、以下のサイトでJavaのプログラムがあった。
https://codezine.jp/article/detail/98
実行しようとしたら、Appletだったので、もっと簡単に実行できるように、Swingで書き直してみた。
ついでに汎用的な画像でも使えるようにしたり、色々とリファクタリングした。

■ サンプル

 * 使用する画像は、ペイントで適当に白黒でテストデータ画像を作って実行した

Main.java

import javax.swing.JFrame;

public class Main {
  public static void main(String[] args) {
    try {
      JFrame frame = new JFrame("Thinning Demo");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      ThinningPanel panel = new ThinningPanel("C:\\temp\\sample.png");
      frame.add(panel);
      frame.pack();
      frame.setSize(1200, 500);
      frame.setVisible(true);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
}

ThinningPanel.java

import java.awt.Color;
import java.awt.Graphics;
import java.awt.MediaTracker;
import java.awt.image.BufferedImage;
import java.awt.image.PixelGrabber;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class ThinningPanel extends JPanel {
  private static final long serialVersionUID = 1L;

  private final static int UPPER_LEFT = 2;
  private final static int LOWER_RIGHT = 6;
  private final static int UPPER_RIGHT = 0;
  private final static int LOWER_LEFT = 4;
  private final static byte BLACK = 1;
  private final static byte WHITE = 0;
  private final static int THRESHOLD = 128;

  private BufferedImage srcImage;
  private boolean hasChanged;
  private byte[][] newPixels;
  private byte[][] oldPixels;
  private int imageWidth;
  private int imageHeight;

  public ThinningPanel(String imagePath) throws IOException, InterruptedException {
    init(imagePath);
  }

  private void init(String imagePath) throws IOException, InterruptedException {

    File pathToFile = new File(imagePath);
    this.srcImage = ImageIO.read(pathToFile);
    MediaTracker mediaTracker = new MediaTracker(this);
    mediaTracker.addImage(this.srcImage, 0);
    mediaTracker.waitForAll();
    this.imageWidth = this.srcImage.getWidth();
    this.imageHeight = this.srcImage.getHeight();
    this.newPixels = new byte[this.imageWidth + 2][this.imageHeight + 2];
    this.oldPixels = new byte[this.imageWidth + 2][this.imageHeight + 2];
    this.toBinaryExpanded(this.srcImage, this.imageWidth, this.imageHeight);

  }

  // 原画像を拡張し、細線化のための二次元二値データを生成するメソッド
  private void toBinaryExpanded(BufferedImage image, int width, int height) {
    int[] rgbPixcels = new int[width * height];

    // 原画像imgを一次元RGBデータrgb[]にする
    PixelGrabber grabber = new PixelGrabber(image, 0, 0, width, height, rgbPixcels, 0, width);
    try {
      grabber.grabPixels();
    } catch (InterruptedException e) {
    }

    // 拡張画像を作り、その二次元二値データをすべて白(0)に設定する
    for (int j = 0; j < height + 2; j++) {
      for (int i = 0; i < width + 2; i++) {
        this.newPixels[i][j] = WHITE;
      }
    }

    // 原画像の一次元RGBデータrgbPixcels[]を、
    // 拡張画像の中央部に二次元化して書き込む
    for (int j = 1; j < height + 1; j++) {
      for (int i = 1; i < width + 1; i++) {
        Color color = new Color(rgbPixcels[(j - 1) * width + (i - 1)]);
        int redValue = color.getRed();
        if (redValue < THRESHOLD) {
          // 黒に設定
          this.newPixels[i][j] = BLACK;
        }
      }
    }
  }

  @Override
  protected void paintComponent(Graphics graphics) {
    int width = this.imageWidth + 2;
    int height = this.imageHeight + 2;

    // 原画像を画面の左側に描画
    graphics.drawImage(this.srcImage, 10, 10, null);

    // 細線化を実施する
    do {

      this.hasChanged = false;

      // 描画とコピー
      this.drawAndCopy(graphics, width, height);
      // 左上から細線化
      for (int j = 1; j < height - 1; j++) {
        for (int i = 1; i < width - 1; i++) {
          if (oldPixels[i][j] == BLACK) {
            this.thinImage(i, j, UPPER_LEFT);
          }
        }
      }

      // 描画とコピー
      this.drawAndCopy(graphics, width, height);
      // 右下から細線化
      for (int j = height - 2; j >= 1; j--) {
        for (int i = width - 2; i >= 1; i--) {
          if (this.oldPixels[i][j] == BLACK) {
            this.thinImage(i, j, LOWER_RIGHT);
          }
        }
      }

      // 描画とコピー
      this.drawAndCopy(graphics, width, height);
      // 右上から細線化
      for (int j = 1; j < height - 1; j++) {
        for (int i = width - 2; i >= 1; i--) {
          if (this.oldPixels[i][j] == BLACK) {
            this.thinImage(i, j, UPPER_RIGHT);
          }
        }
      }

      // 描画とコピー
      this.drawAndCopy(graphics, width, height);
      // 左下から細線化
      for (int j = height - 2; j >= 1; j--) {
        for (int i = 1; i < width - 1; i++) {
          if (this.oldPixels[i][j] == BLACK) {
            this.thinImage(i, j, LOWER_LEFT);
          }
        }
      }
    } while (this.hasChanged);
  }

  // 描画とコピーのメソッド
  private void drawAndCopy(Graphics graphics, int width, int height) {
    for (int j = 0; j < height; j++) {
      for (int i = 0; i < width; i++) {
        if (this.newPixels[i][j] == BLACK) {
          graphics.setColor(Color.black);
        } else {
          graphics.setColor(Color.white);
        }

        // 細線化画像を画面右側に描画
        graphics.drawRect(this.imageWidth + 40 + i, 10 + j, 1, 1);
        // 次の細線化のためのコピー
        this.oldPixels[i][j] = this.newPixels[i][j];
      }
    }
  }

  // 細線化のメソッド
  public void thinImage(int i, int j, int start) {

    byte[] pixcels = new byte[8];
    pixcels[0] = this.oldPixels[i - 1][j - 1];
    pixcels[1] = this.oldPixels[i - 1][j];
    pixcels[2] = this.oldPixels[i - 1][j + 1];
    pixcels[3] = this.oldPixels[i][j + 1];
    pixcels[4] = this.oldPixels[i + 1][j + 1];
    pixcels[5] = this.oldPixels[i + 1][j];
    pixcels[6] = this.oldPixels[i + 1][j - 1];
    pixcels[7] = this.oldPixels[i][j - 1];

    for (int k = start; k < start + 3; k++) {
      int product = pixcels[k % 8] * pixcels[(k + 1) % 8] * pixcels[(k + 2) % 8];
      int sum = pixcels[(k + 4) % 8] + pixcels[(k + 5) % 8] + pixcels[(k + 6) % 8];
      if (product == 1 && sum == 0) {
        // 消去する
        this.newPixels[i][j] = WHITE;
        this.hasChanged = true;
        return;
      }
    }
  }
}

関連記事

二値化 / 領域抽出 / 細線化

https://blogs.yahoo.co.jp/dk521123/37815897.html

【画像処理】二値化 / 領域抽出 / 細線化

$
0
0

■ はじめに

ラスタベクタ変換に調べていたところ、前処理として、以下が必要らしい。
~~~~~~~~~~~~~~
【1】 二値化(にちか)
【2】 領域抽出
【3】 細線化(さいせんか)
~~~~~~~~~~~~~~

また、文字認識やパターン認識の前処理として多く使われるので、メモ。

【1】 二値化

Binarization
 * 画像を白か黒にする処理
  => 次に、画像のどの色(閾値)で、白にするか黒にするかが問題となってくる

閾値の決めるアルゴリズム

a) 閾値指定
 * 決め打ちで閾値を決める
b) Pタイル法
 * 対象の占める画素数が既知の時、画素が低いところから積算して決める
c) 判別分析法(大津の二値化)
 * クラス間分散とクラス内分散により求められる分離法が最大となる閾値をとる
d) モード法
 * 山と山の間の谷底を閾値とする

【2】 領域抽出

 * 画像の領域を分割する処理
 * 対象の領域を切り出して他の領域と区別すること

【3】 細線化

Thinning / Skeletonization
 * 二値画像を幅1ピクセルの線画像に変化する処理

閾値の決めるアルゴリズム

a) Hilditch の方法
https://qiita.com/TatsuyaOGth/items/45965e1632f41f3eb139
b) 田村 の方法
http://imagingsolution.blog.fc2.com/blog-entry-138.html
c) Zhang-Suen の方法
https://qiita.com/hrs1985/items/7751d4b5241d5c314a6d

関連記事

【Java】二値画像の細線化

https://blogs.yahoo.co.jp/dk521123/37816017.html
Viewing all 860 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>