泠音

泠音 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑

想象一座飘着朦胧烟雨的村庄,怎么才能走进她的心里。

个人动态

泠音 发布了文章 · 2019-02-12

Hide Desktop Icon[AutoHotKey]

Hide Desktop Icon[AutoHotKey]

Update

/* Library:
 *      Hide Desktop Icon
 * Description:
 *      Hide the desktop icon by double clicking the right mouse button
 * Warnning:
 *      None.
 * Version:
 *      v1.0.5
 * Author:
 *      泠音
 */

intInterval:=300
~RButton::
    If(A_PriorHotkey <> "~RBUtton" or A_TimeSincePriorHotkey > intInterval){
        KeyWait, RButton
        return
    }
If(check()){
    HideOrShowDesktopIcons()
    Sleep, 40
    Send, {Esc}
    return
}

check(){
    MouseGetPos,X,Y,ID,CLASS
    return CLASS=="SysListView321" 
        or CLASS=="SHELLDLL_DefView1"
        or CLASS==""
        or WinExist("ahk_class WorkerW" . " ahk_id " . CLASS)
}

HideOrShowDesktopIcons()
{
    ControlGet, class, Hwnd,, SysListView321, ahk_class Progman
    If class =
        ControlGet, class, Hwnd,, SysListView321, ahk_class WorkerW
 
    If DllCall("IsWindowVisible", UInt,class)
        WinHide, ahk_id %class%
    Else
        WinShow, ahk_id %class%
}
查看原文

赞 0 收藏 0 评论 0

泠音 发布了文章 · 2019-02-12

Quick Switch Virtual Desktop[AutoHotkey]

Quick Switch Virtual Desktop[AutoHotkey]

Update

/* Library:
 *      Quick Switch Virtual Desktop
 * Description:
 *      在屏幕四周,任务栏,桌面上使用鼠标滚轮来切换虚拟桌面。
 * Warnning:
 *      None.
 * Version:
 *      v1.0.4
 * Author:
 *      泠音
 */

#MaxHotkeysPerInterval 300
WheelUp::
    If (isHook()){
        Send, {LWinDown}{CtrlDown}{Left Down}{LWinUp}{CtrlUp}{Left Up}
    }else{
        MouseClick, WheelUp
    }
    return

WheelDown::
    If (isHook()){
        Send, {LWinDown}{CtrlDown}{Right Down}{LWinUp}{CtrlUp}{Right Up}
    }else{
        MouseClick, WheelDown
    }
    return

isHook(){
    CoordMode, Mouse,Screen
    MouseGetPos, X,Y,ID,CLASS
    ; t1 := A_ScreenWidth-X
    ; t2 := A_ScreenHeight-Y
    ; MsgBox X:%X% Y:%Y% dw:%t1% dh:%t2% W:%A_ScreenWidth% H:%A_ScreenHeight%
    return MouseIsOver("ahk_class WorkerW") 
        or MouseIsOver("ahk_class Shell_TrayWnd") 
        or X==0 
        or Y==0
        or A_ScreenWidth-X<2
        or A_ScreenHeight-Y<2
        or CLASS=="SysListView321"
        or CLASS=="SHELLDLL_DefView1"
}

MouseIsOver(WinTitle) {
    MouseGetPos,,, Win
    return WinExist(WinTitle . " ahk_id " . Win)
}
查看原文

赞 0 收藏 0 评论 0

泠音 发布了文章 · 2019-02-09

PowerShell批量设置PATH环境变量

PowerShell批量设置PATH环境变量

Code

#requires -version 4.0
#requires #-runasadministrator

# Get the ID and security principal of the current user account
$myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID);

# Get the security principal for the administrator role
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;

# Check to see if we are currently running as an administrator
if ($myWindowsPrincipal.IsInRole($adminRole))
{
    # We are running as an administrator, so change the title and background colour to indicate this
    $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)";
    $Host.UI.RawUI.BackgroundColor =0;
    Clear-Host;
}
else {
    # We are not running as an administrator, so relaunch as administrator

    # Create a new process object that starts PowerShell
    $newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell";

    # Specify the current script path and name as a parameter with added scope and support for scripts with spaces in it's path
    $newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"

    # Indicate that the process should be elevated
    $newProcess.Verb = "runas";

    # Start the new process
    [System.Diagnostics.Process]::Start($newProcess);

    # Exit from the current, unelevated, process
    Exit;
}


$file=Get-Content -Path $PSScriptRoot"/env.txt"

$path=$env:Path

$floders=$env:Path.Split(";")

$index=0

foreach($line in $file){
    if($floders.Contains($line)){
        Write-Host $line" already exists in PATH variable!"
    }
    else{
        if($path.Trim().EndsWith(";")){
            $path=$path+$line
        }
        else{
            $path=$path+";"+$line
        }
        [System.Environment]::SetEnvironmentVariable("Path",$path,"Machine")
        $index++
        Write-Host $index ": " "Add "  $line "to PATH variable!"
    }
}

cmd /c "pause"

EnvTxt

D:\Micro\Android\Sdk\platform-tools
D:\Program Files\cmder_mini
D:\MinGW\bin
D:\cmake\bin
C:\Program Files\MySQL\MySQL Server 8.0\bin
D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\Scripts
D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64
C:\Program Files\Java\jdk-11.0.2\bin
C:\Program Files\Java\jdk-11.0.2\jre\bin
D:\Program Files\Git\cmd
C:\Program Files\Microsoft SQL Server\130\Tools\Binn\
D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\Scripts\
D:\Program Files (x86)\Microsoft Visual Studio\Shared\Python37_64\

注意事项

  1. EnvTxt 必须为env.txt,且需要与ps脚本位于同一目录下
    img

使用方法

在ps1脚本文件右键选择使用 PowerShell 运行,然后确认UAC提示框即可。
img

运行结果

img

查看原文

赞 0 收藏 0 评论 0

泠音 发布了文章 · 2019-02-05

JavaFx中Controller获取Stage并自定义窗口移动与缩放逻辑

JavaFx中Controller获取Stage并自定义窗口移动与缩放逻辑

由于去掉了平台自带了标题栏,窗口就无法移动和缩放了,需要我们自己来实现。

去除窗口标题栏

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));
        primaryStage.setTitle("main");
        // 主要是这一句
        primaryStage.initStyle(StageStyle.TRANSPARENT);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }


    public static void main(String[] args) {
        launch(args);
    }
}

在Controller中获取Stage

首先确定在Controller中获取到你的跟布局对象,如下:

public class Controller implements Initializable {
    public BorderPane root;
    private Stage stage;
}
<BorderPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" stylesheets="@../css/main.css" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="line.main.Controller">
      <!--其他布局元素-->
</BorderPane>

然后可以在public void initialize(URL url, ResourceBundle resourceBundle) 方法内获取Stage

public class Controller implements Initializable {
    public BorderPane root;
    private Stage stage;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
       var stage = getStage();
    }

    private Stage getStage() {
        if (stage == null) {
            stage = (Stage) root.getScene().getWindow();
        }
        return stage;
    }

}

自定义窗体移动与缩放逻辑

  1. 记录鼠标坐标

     root.setOnMousePressed(event -> {
                event.consume();
                xOffset = event.getSceneX();
                yOffset = event.getSceneY();
            });
  2. 自定义移动控制区域

    dragArea.setOnMouseDragged(event -> {
                event.consume();
                var stage = getStage();
                stage.setX(event.getScreenX() - xOffset);
                stage.setY(event.getScreenY() - yOffset);
            });
  3. 判断鼠标坐标位置,并处理光标变换

    root.setOnMouseMoved(this::mouseMoveHandle);
    
     private void mouseMoveHandle(MouseEvent event) {
            event.consume();
            double x = event.getSceneX();
            double y = event.getSceneY();
            var stage = getStage();
            double width = stage.getWidth();
            double height = stage.getHeight();
            Cursor cursorType = Cursor.DEFAULT;
            bit = 0;
            if (y >= height - RESIZE_WIDTH) {
                if (x <= RESIZE_WIDTH) {
                    bit |= 1 << 3;
                } else if (x >= width - RESIZE_WIDTH) {
                    bit |= 1;
                    bit |= 1 << 2;
                    cursorType = Cursor.SE_RESIZE;
                } else {
                    bit |= 1;
                    cursorType = Cursor.S_RESIZE;
                }
            } else if (x >= width - RESIZE_WIDTH) {
                bit |= 1 << 2;
                cursorType = Cursor.E_RESIZE;
            }
            root.setCursor(cursorType);
        }
  4. 处理窗口缩放

    root.setOnMouseDragged(this::mouseDraggedHandle);
    
    private void mouseDraggedHandle(MouseEvent event) {
        event.consume();
        var primaryStage = getStage();
        double x = event.getSceneX();
        double y = event.getSceneY();
        double nextX = primaryStage.getX();
        double nextY = primaryStage.getY();
        double nextWidth = primaryStage.getWidth();
        double nextHeight = primaryStage.getHeight();
        if ((bit & 1 << 2) != 0) {
            nextWidth = x;
        }
        if ((bit & 1) != 0) {
            nextHeight = y;
        }
        if (nextWidth <= MIN_WIDTH) {
            nextWidth = MIN_WIDTH;
        }
        if (nextHeight <= MIN_HEIGHT) {
            nextHeight = MIN_HEIGHT;
        }
        primaryStage.setX(nextX);
        primaryStage.setY(nextY);
        primaryStage.setWidth(nextWidth);
        primaryStage.setHeight(nextHeight);
    }

完整代码

package line.main;

import javafx.fxml.Initializable;
import javafx.scene.Cursor;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;

import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable {
    public BorderPane root;
    public Pane dragArea;
    private Stage stage;
    private double xOffset = 0;
    private double yOffset = 0;
    private int bit = 0;//left,right,top,bottom
    private static final double RESIZE_WIDTH = 5.00;
    private static final double MIN_WIDTH = 600.00;
    private static final double MIN_HEIGHT = 400.00;

    @Override
    public void initialize(URL url, ResourceBundle resourceBundle) {
        dragArea.setOnMouseDragged(event -> {
            event.consume();
            var stage = getStage();
            stage.setX(event.getScreenX() - xOffset);
            stage.setY(event.getScreenY() - yOffset);
        });
        root.setOnMousePressed(event -> {
            event.consume();
            xOffset = event.getSceneX();
            yOffset = event.getSceneY();
        });
        root.setOnMouseMoved(this::mouseMoveHandle);
        root.setOnMouseDragged(this::mouseDraggedHandle);
    }

    private Stage getStage() {
        if (stage == null) {
            stage = (Stage) root.getScene().getWindow();
        }
        return stage;
    }

    private void mouseMoveHandle(MouseEvent event) {
        event.consume();
        double x = event.getSceneX();
        double y = event.getSceneY();
        var stage = getStage();
        double width = stage.getWidth();
        double height = stage.getHeight();
        Cursor cursorType = Cursor.DEFAULT;
        bit = 0;
        if (y >= height - RESIZE_WIDTH) {
            if (x <= RESIZE_WIDTH) {
                bit |= 1 << 3;
            } else if (x >= width - RESIZE_WIDTH) {
                bit |= 1;
                bit |= 1 << 2;
                cursorType = Cursor.SE_RESIZE;
            } else {
                bit |= 1;
                cursorType = Cursor.S_RESIZE;
            }
        } else if (x >= width - RESIZE_WIDTH) {
            bit |= 1 << 2;
            cursorType = Cursor.E_RESIZE;
        }
        root.setCursor(cursorType);
    }

    private void mouseDraggedHandle(MouseEvent event) {
        event.consume();
        var primaryStage = getStage();
        double x = event.getSceneX();
        double y = event.getSceneY();
        double nextX = primaryStage.getX();
        double nextY = primaryStage.getY();
        double nextWidth = primaryStage.getWidth();
        double nextHeight = primaryStage.getHeight();
        if ((bit & 1 << 2) != 0) {
            nextWidth = x;
        }
        if ((bit & 1) != 0) {
            nextHeight = y;
        }
        if (nextWidth <= MIN_WIDTH) {
            nextWidth = MIN_WIDTH;
        }
        if (nextHeight <= MIN_HEIGHT) {
            nextHeight = MIN_HEIGHT;
        }
        primaryStage.setX(nextX);
        primaryStage.setY(nextY);
        primaryStage.setWidth(nextWidth);
        primaryStage.setHeight(nextHeight);
    }
}
查看原文

赞 0 收藏 0 评论 0

泠音 发布了文章 · 2019-02-05

Idea VM options

# Custom IntelliJ IDEA VM options

##################JVM模式############################

# IDEA的JVM以Server模式启动(新生代默认使用ParNew)
-server


##################内存分配###########################

# 堆初始值占用3G,意味着IDEA启动即分配3G内存
-Xms3g

# 堆最大值占用3G
-Xmx3g

# 强制JVM在启动时申请到足够的堆内存(否则IDEA启动时堆初始大小不足3g)
-XX:+AlwaysPreTouch

# 年轻代与老年代比例为1:3(默认值是1:4),降低年轻代的回收频率
-XX:NewRatio=3

# 栈帧大小为16m
-Xss16m

##################老年代回收器########################

# 使用CMS老年代回收器
-XX:+UseConcMarkSweepGC

# CMS的重新标记步骤:多线程一起执行
-XX:+CMSParallelRemarkEnabled

# CMS的并发标记步骤:启用4个线程并发标记(理论上越多越好,前提是CPU核心足够多)
-XX:ConcGCThreads=8


##################JIT编译器###########################

# 代码缓存,用于存放Just In Time编译后的本地代码,如果塞满,JVM将只解释执行,不再编译native代码。
-XX:ReservedCodeCacheSize=512m

# 分层编译,JIT编译优化越来越好,IDEA运行时间越久越快
-XX:+TieredCompilation

# 节省64位指针占用的空间,代价是JVM额外开销
#-XX:+UseCompressedOops

# 增大软引用在JVM中的存活时长(堆空闲空间越大越久)
-XX:SoftRefLRUPolicyMSPerMB=50

# 设为false Idea会提示无法利用Https更新
-Djsse.enableSNIExtension=true

-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-XX:MaxJavaStackTraceDepth=10000
-Dide.no.platform.update=true
查看原文

赞 6 收藏 4 评论 1

泠音 发布了文章 · 2019-02-05

Kotlin/Native尝试

Kotlin/Native尝试

在官网看到Kotlin/Native已经达到1.0 Beta版于是就去尝试了一下,结果发现坑还是挺多的。
首先Kotlin/JVM很多库是用不了的,这个已经猜到了。官网说已经预先导入了 POSIX、 gzip、 OpenGL、 Metal、 Foundation 等很多其他的库,然后我就尝试了下基本的文件读写。和C还是有一点的差别的。如下:

fun hello(): String = "Hello, Kotlin/Native!"
fun letter() = "abcdefghigklmnopqrstuvwxyz"

fun main(args: Array<String>) {
    val file = fopen("data.txt", "w")
    fprintf(file, "%s", hello())
    fprintf(file, "%s", "\n")
    fprintf(file, "%s", letter())
    fclose(file)
    println("write finished")
    val filer = fopen("data.txt", "r")
    val buf = ByteArray(255)
//    fscanf(filer, "%s", buf.pin().addressOf(0))
    fgets(buf.pin().addressOf(0), 255, filer)
    fclose(filer)
    print(buf.stringFromUtf8())
    buf.pin().unpin()
    println("read finished")
    system("pause")
}

运行结果如下

> Task :runProgram
write finished
Hello, Kotlin/Native!
read finished
Press any key to continue . . . 
C:\BuildAgent\work\4d622a065c544371\runtime\src\main\cpp\Memory.cpp:1150: runtime assert: Memory leaks found

> Task :runProgram FAILED

令人郁闷的是提示C:\BuildAgent\work\4d622a065c544371\runtime\src\main\cpp\Memory.cpp:1150: runtime assert: Memory leaks found,虽然调用了buf.pin().unpin(),但依旧提示内存泄漏,也没有异常退出啊。

如果是改成如下方式就不会提示错误了:

fun hello(): String = "Hello, Kotlin/Native!"
fun letter() = "abcdefghigklmnopqrstuvwxyz"

fun main(args: Array<String>) {
    val file = fopen("data.txt", "w")
    fprintf(file, "%s", hello())
    fprintf(file, "%s", "\n")
    fprintf(file, "%s", letter())
    fclose(file)
    println("write finished")
    val filer = fopen("data.txt", "r")
    val buf = ByteArray(255)
//    fscanf(filer, "%s", buf.pin().addressOf(0))
//    fgets(buf.pin().addressOf(0), 255, filer)
//    fclose(filer)
//    print(buf.stringFromUtf8())
//    buf.pin().unpin()
    buf.usePinned {
        fgets(it.addressOf(0), 255, filer)
        fclose(filer)
        print(buf.stringFromUtf8())
    }
    println("read finished")
    system("pause")
}

结果如下:

> Task :runProgram
write finished
Hello, Kotlin/Native!
read finished
Press any key to continue . . . 

BUILD SUCCESSFUL in 9s

另外吐槽下,这么几行代码就要9s,是不是太慢了。

随后又试了下开启pthread线程,但是pthread_create函数的第一个参数th: kotlinx.cinterop.CValuesRef<platform.posix.pthread_tVar>CValuesRef类型的变量怎么获得一直无解,难道只能通过继承获得?

然后我在写文章的时候又发现只要这样写就可以了???

fun main(args: Array<String>) {
    pthread_create(null, null, test(), null)
}

typealias func = kotlinx.cinterop.CPointer<kotlinx.cinterop.CFunction<(kotlinx.cinterop.COpaquePointer?) -> kotlinx.cinterop.COpaquePointer?>>?

fun test(): func {
    return staticCFunction<kotlinx.cinterop.COpaquePointer?, kotlinx.cinterop.COpaquePointer?> {
        println("run test")
        it
    }
}

结果如下:

> Task :runProgram
run test
BUILD SUCCESSFUL in 8s
查看原文

赞 1 收藏 1 评论 0

泠音 发布了文章 · 2019-02-04

Idea插件使用

Idea

activate-power-mode

activate-power-mode for IDEA.
根据Atom的插件activate-power-mode的效果移植到IDEA上

设置窗口在这里:

setting

我喜欢打开colorful关闭combo,你们呢?

Download

Atom Material Icons

Replace Jetbrains' icons with Atom File Icons and Material Design Icons! This is a both a port of the Atom File Icons (https://github.com/file-icons... and the Material Theme Icons (https://github.com/ChrisRM/ma... for Jetbrains products.

它好像会随着Material Theme UI一起安装。

Download

Material Theme UI

This will add the Material Theme look to your IDE.

很棒的一个主题
设置在这里:
setting

Download

Rainbow Brackets

Rainbow Brackets / Rainbow Parentheses for IntelliJ based IDEs
Supported languages:

Java, Scala, Clojure, Kotlin, Python, Haskell, Agda, Rust, JavaScript, TypeScript, Erlang, Go, Groovy, Ruby, Elixir, ObjectiveC, PHP, HTML, XML, SQL, Apex language, C#, Dart ...

Java

img

With Material Theme UI

img

Scala

img

Kotlin

img

Clojure

img

Html

img

Gif

img
img

Download

WakaTime

Metrics, insights, and time tracking automatically generated from your programming activity.

Installation

  1. Inside your IDE, select Preferences -> Plugins -> Browse Repositories....
  2. Search for wakatime.
  3. Click the green Install Plugin button and confirm the installation.
  4. Re-launch your IDE.
  5. Enter your api key, then click Save.
  6. Use your IDE like you normally do and your time will be tracked for you automatically.
  7. Visit https://wakatime.com to see your logged time.

Source Code: https://github.com/wakatime/j...

setting

chrome也有哦,附一张我的统计图:

myimg

设置在这里:

setting

Download

Android Studio

Android WiFi ADB

Provides an action which allow you quickly connect your Android device over WiFi to install, run and debug your applications without a USB connected by pressing one button.
Connect your device using a USB cable and press the Android WiFi ADB button. Once the device be connected over WiFi you'll see an IntelliJ/Android Studio notification. Now you can disconnect your USB cable and enjoy deploying, running and debugging your applications over WiFi.
The version 2.0 enables a window to check which of your devices are connected or not and connect/disconnect it manually if needed.

img

有了它就不用数据先连接调试了,需要在同一个局域网下哦。

Download

Database Navigator

Database development, scripting and navigation tool
This product adds extensive database development and maintenance capabilities to the IntelliJ IDEA development environment and related products. Along with a qualified and IDE-compliant SQL and PL/SQL editor, it provides advanced database connection management, script execution support, database objects browsing, data and code editor, support for database compiler operations, method execution and debugging, database objects factory, as well as various navigation capabilities between all its components.
See features overview on the support page.

Supported Databases:
Oracle
MySQL
SQLite
PostgreSQL

This tool is free for personal and commercial usage.
Donations are very welcome though.

调试数据库有奇效。

Download

JSON To Kotlin Class (JsonToKotlinClass)

Plugin for Kotlin to convert Json String into Kotlin data class code quickly

Fast use it with short cut key ALT + K on Windows or Option + K on Mac

Features:

Generating Kotlin data class from any legal JSON string or any URLs that returns a JSON string as response
Generating Kotlin data class from any legal JSON text when right click on directory and select New -> Kotlin data class File from JSON

Supporting (almostly) all kinds of JSON libs' annotation(Gson, Jackson, Fastjson, MoShi and LoganSquare, kotlinx.serialization(default custom value))

Customizing your own annotations

Initializing properties with default values

Allowing properties to be nullable(?)

Determining property nullability automatically

Renaming property names to be camelCase style when selecting a target JSON lib annotation.

Generating Kotlin data class as individual classes

Generating Kotlin data class as inner classes

Formatting any legal JSON string

Generating Map Type when json key is primitive type

Only create annotation when needed

Custom define data class parent class

Sort property order by Alphabetical

Make keyword property valid

Support Loading JSON From Paster/Local File/Http URL

Support customize your own plugin by Extension Module

usage

usage

Full Usage Documentation

Download

未完待续

查看原文

赞 1 收藏 0 评论 0

泠音 发布了文章 · 2019-02-04

Tensorflow分类器项目自定义数据读入

Tensorflow分类器项目自定义数据读入

在照着Tensorflow官网的demo敲了一遍分类器项目的代码后,运行倒是成功了,结果也不错。但是最终还是要训练自己的数据,所以尝试准备加载自定义的数据,然而demo中只是出现了fashion_mnist.load_data()并没有详细的读取过程,随后我又找了些资料,把读取的过程记录在这里。
首先提一下需要用到的模块:

import os

import keras
import matplotlib.pyplot as plt
from PIL import Image
from keras.preprocessing.image import ImageDataGenerator
from sklearn.model_selection import train_test_split

图片分类器项目,首先确定你要处理的图片分辨率将是多少,这里的例子为30像素:

IMG_SIZE_X = 30
IMG_SIZE_Y = 30

其次确定你图片的方式目录:

image_path = r'D:\Projects\ImageClassifier\data\set'
path = ".\data"
# 你也可以使用相对路径的方式
# image_path =os.path.join(path, "set")

目录下的结构如下:

folder

相应的label.txt如下:

动漫
风景
美女
物语
樱花

接下来是接在labels.txt,如下:

label_name = "labels.txt"
label_path = os.path.join(path, label_name)
class_names = np.loadtxt(label_path, type(""))

这里简便起见,直接利用了numpy的loadtxt函数直接加载。

之后便是正式处理图片数据了,注释就写在里面了:

re_load = False
re_build = False
# re_load = True
re_build = True

data_name = "data.npz"
data_path = os.path.join(path, data_name)
model_name = "model.h5"
model_path = os.path.join(path, model_name)

count = 0

# 这里判断是否存在序列化之后的数据,re_load是一个开关,是否强制重新处理,测试用,可以去除。
if not os.path.exists(data_path) or re_load:
    labels = []
    images = []
    print('Handle images')
    # 由于label.txt是和图片防止目录的分类目录一一对应的,即每个子目录的目录名就是labels.txt里的一个label,所以这里可以通过读取class_names的每一项去拼接path后读取
    for index, name in enumerate(class_names):
        # 这里是拼接后的子目录path
        classpath = os.path.join(image_path, name)
        # 先判断一下是否是目录
        if not os.path.isdir(classpath):
            continue
        # limit是测试时候用的这里可以去除
        limit = 0
        for image_name in os.listdir(classpath):
            if limit >= max_size:
                break
            # 这里是拼接后的待处理的图片path
            imagepath = os.path.join(classpath, image_name)
            count = count + 1
            limit = limit + 1
            # 利用Image打开图片
            img = Image.open(imagepath)
            # 缩放到你最初确定要处理的图片分辨率大小
            img = img.resize((IMG_SIZE_X, IMG_SIZE_Y))
            # 转为灰度图片,这里彩色通道会干扰结果,并且会加大计算量
            img = img.convert("L")
            # 转为numpy数组
            img = np.array(img)
            # 由(30,30)转为(1,30,30)(即`channels_first`),当然你也可以转换为(30,30,1)(即`channels_last`)但为了之后预览处理后的图片方便这里采用了(1,30,30)的格式存放
            img = np.reshape(img, (1, IMG_SIZE_X, IMG_SIZE_Y))
            # 这里利用循环生成labels数据,其中存放的实际是class_names中对应元素的索引
            labels.append([index])
            # 添加到images中,最后统一处理
            images.append(img)
            # 循环中一些状态的输出,可以去除
            print("{} class: {} {} limit: {} {}"
                  .format(count, index + 1, class_names[index], limit, imagepath))
    # 最后一次性将images和labels都转换成numpy数组
    npy_data = np.array(images)
    npy_labels = np.array(labels)
    # 处理数据只需要一次,所以我们选择在这里利用numpy自带的方法将处理之后的数据序列化存储
    np.savez(data_path, x=npy_data, y=npy_labels)
    print("Save images by npz")
else:
    # 如果存在序列化号的数据,便直接读取,提高速度
    npy_data = np.load(data_path)["x"]
    npy_labels = np.load(data_path)["y"]
    print("Load images by npz")
image_data = npy_data
labels_data = npy_labels

到了这里原始数据的加工预处理便已经完成,只需要最后一步,就和demo中fashion_mnist.load_data()返回的结果一样了。代码如下:

# 最后一步就是将原始数据分成训练数据和测试数据
train_images, test_images, train_labels, test_labels = \
    train_test_split(image_data, labels_data, test_size=0.2, random_state=6)

这里将相关信息打印的方法也附上:

print("_________________________________________________________________")
print("%-28s %-s" % ("Name", "Shape"))
print("=================================================================")
print("%-28s %-s" % ("Image Data", image_data.shape))
print("%-28s %-s" % ("Labels Data", labels_data.shape))
print("=================================================================")

print('Split train and test data,p=%')
print("_________________________________________________________________")
print("%-28s %-s" % ("Name", "Shape"))
print("=================================================================")
print("%-28s %-s" % ("Train Images", train_images.shape))
print("%-28s %-s" % ("Test Images", test_images.shape))
print("%-28s %-s" % ("Train Labels", train_labels.shape))
print("%-28s %-s" % ("Test Labels", test_labels.shape))
print("=================================================================")

之后别忘了归一化哟:

print("Normalize images")
train_images = train_images / 255.0
test_images = test_images / 255.0

最后附上读取自定义数据的完整代码:

import os

import keras
import matplotlib.pyplot as plt
from PIL import Image
from keras.layers import *
from keras.models import *
from keras.optimizers import Adam
from keras.preprocessing.image import ImageDataGenerator
from sklearn.model_selection import train_test_split

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False  # 用来正常显示负号
re_load = False
re_build = False
# re_load = True
re_build = True
epochs = 50
batch_size = 5
count = 0
max_size = 2000000000
IMG_SIZE_X = 30
IMG_SIZE_Y = 30
np.random.seed(9277)
image_path = r'D:\Projects\ImageClassifier\data\set'
path = ".\data"
data_name = "data.npz"
data_path = os.path.join(path, data_name)
model_name = "model.h5"
model_path = os.path.join(path, model_name)
label_name = "labels.txt"
label_path = os.path.join(path, label_name)
class_names = np.loadtxt(label_path, type(""))
print('Load class names')
if not os.path.exists(data_path) or re_load:
    labels = []
    images = []
    print('Handle images')
    for index, name in enumerate(class_names):
        classpath = os.path.join(image_path, name)
        if not os.path.isdir(classpath):
            continue
        limit = 0
        for image_name in os.listdir(classpath):
            if limit >= max_size:
                break
            imagepath = os.path.join(classpath, image_name)
            count = count + 1
            limit = limit + 1
            img = Image.open(imagepath)
            img = img.resize((30, 30))
            img = img.convert("L")
            img = np.array(img)
            img = np.reshape(img, (1, 30, 30))
            # img = skimage.io.imread(imagepath, as_grey=True)
            # if img.shape[2] != 3:
            #     print("{} shape is {}".format(image_name, img.shape))
            #     continue
            # data = transform.resize(img, (IMG_SIZE_X, IMG_SIZE_Y))
            labels.append([index])
            images.append(img)
            print("{} class: {} {} limit: {} {}"
                  .format(count, index + 1, class_names[index], limit, imagepath))
    npy_data = np.array(images)
    npy_labels = np.array(labels)
    np.savez(data_path, x=npy_data, y=npy_labels)
    print("Save images by npz")
else:
    npy_data = np.load(data_path)["x"]
    npy_labels = np.load(data_path)["y"]
    print("Load images by npz")
image_data = npy_data
labels_data = npy_labels
print("_________________________________________________________________")
print("%-28s %-s" % ("Name", "Shape"))
print("=================================================================")
print("%-28s %-s" % ("Image Data", image_data.shape))
print("%-28s %-s" % ("Labels Data", labels_data.shape))
print("=================================================================")
train_images, test_images, train_labels, test_labels = \
    train_test_split(image_data, labels_data, test_size=0.2, random_state=6)
print('Split train and test data,p=%')
print("_________________________________________________________________")
print("%-28s %-s" % ("Name", "Shape"))
print("=================================================================")
print("%-28s %-s" % ("Train Images", train_images.shape))
print("%-28s %-s" % ("Test Images", test_images.shape))
print("%-28s %-s" % ("Train Labels", train_labels.shape))
print("%-28s %-s" % ("Test Labels", test_labels.shape))
print("=================================================================")

# 归一化
# 我们将这些值缩小到 0 到 1 之间,然后将其馈送到神经网络模型。为此,将图像组件的数据类型从整数转换为浮点数,然后除以 255。以下是预处理图像的函数:
# 务必要以相同的方式对训练集和测试集进行预处理:
print("Normalize images")
train_images = train_images / 255.0
test_images = test_images / 255.0
查看原文

赞 0 收藏 0 评论 0

泠音 发布了文章 · 2019-02-04

Google Translate的API调用

Google Translate的API调用

由于经常用到谷歌翻译,而每次切换到网页又觉得耗费时间,所以决定自己写一个小工具来用,于是就去查询了一番谷歌翻译的API,但是看到都说是API已经开始收费了,但还是有人通过网页爬出了网页翻译的API但是利用起来比较繁琐。之后又找到了一个简单的API,如下:

fun translate(text: String, source: String = "auto", target: String = "zh-CN"): Pair<String, String> {
    val textChecked = if (text.isBlank()) "null" else URLEncoder.encode(text, "utf8")
    val userAgent = "Mozilla/5.0"
    val url = "https://translate.googleapis.com/translate_a/single?client=gtx&sl=$source&tl=$target&dt=t&q=$textChecked"
    val connection = URL(url).openConnection().apply { setRequestProperty("User-Agent", userAgent) }
    val raw = connection.getInputStream().use { it.readBytes() }.toString(Charset.forName("utf8"))
    val p1 = raw.indexOf("\",\"")
    val p2 = raw.indexOf("\",", p1 + 1)
    val result = raw.substring(4, p1)
    val query = raw.substring(p1 + 3, p2)
    return Pair(result, query)
}

测试函数如下:

fun main() {
    println(translate("别让这么应景的天空放晴啊"))
    println(translate("空気を読んだ空晴れないでよ"))

    println(translate("别降下这么看场合的雨啊"))
    println(translate("空気を読んだ雨降らないでよ"))

    println(translate("He sits no sure that sits too high"))
    println(translate("高处不胜寒", target = "en-US"))
}

调用结果如下:

(别让这么应景的天空放晴啊, 别让这么应景的天空放晴啊)
(我看空中的天空请不要晴天, 空気を読んだ空晴れないでよ)

(别降下这么看场合的雨啊, 别降下这么看场合的雨啊)
(看风雨时不要下雨, 空気を読んだ雨降らないでよ)

(他不确定是不是太高了, He sits no sure that sits too high)
(High altitude, 高处不胜寒)

translate函数参数分别是:需要翻译的字符串,原始语言(默认为auto,即自动检测),目标语言(默认zh-CN,即简体中文)。
translate函数返回结果为:翻译后的字符串,需要翻译的字符串(原始字符串)。

查看原文

赞 0 收藏 0 评论 0

泠音 评论了文章 · 2019-01-21

在VSCode中编写Kotlin/Java

在VSCode中编写Kotlin/Java

前言

不希望每次运行一下代码就要去启动Android Studio这个庞然大物,正好vscode可以做一个轻量级的IDE,所以配置了vscode用来编写Kotlin程序

环境配置

首先可以在Android Studio的安装目录下找到Kotlin Compiler:
1
1
在环境变量中添加以下项:
值为:Kotlin Compiler Pathbin
例如:D:Program FilesAndroidAndroid StudiopluginsKotlinkotlincbin
1
然后再控制台输入命令kotlinc -version检测环境是否配置妥当
如果正常,则如下图所示
1
如果出现这种情况
1
则是jdk版本配置不正确或者JAVA环境配置错误所致,重新配置即可(推荐使用jdk1.8)

配置VSCODE

在vscode扩展中安装Kotlin Language和Code Runner这两个扩展包
1
1
安装后重启加载扩展,就可以编写Kotlin代码并编译运行了,右键Run Code或者Ctrl+Alt+N运行程序,,OK,像这样
1
但是我们发现,输出面板中文出现了乱码,可行的解决办法是在用户设置中添加一句"code-runner.runInTerminal": true,,表示让Kotlin程序通过Terminal运行,就不会出现中文乱码了
效果如下:
1
而且在程序目录下还会生成相应的jar包,如:
1

总结

至此,vscode关于Kotlin的配置就已经完成了.

Enjoy Your Code!
2018/08/31

查看原文

认证与成就

  • 获得 16 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-10-18
个人主页被 483 人浏览