[Python, Программирование, Java, Kotlin] Распознавание текста на картинке с помощью tesseract на Kotlin
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Ни для кого не секрет, что Python прочно занял первенство в ML и Data Science. А что если посмотреть на другие языки и платформы? Насколько в них удобно делать аналогичные решения?
К примеру, распознавание текста на картинке.
Среди текущих решений одним из наиболее распространённым инструментом является tesseract. В Python для него существует удобная библиотека, а для первоначальной обработки изображений, как правило, используется OpenCV. Для обоих этих инструментов есть исходные C++ библиотеки, поэтому их также возможно вызывать и из других экосистем. Попробуем это сделать в jvm и, в частности, на Kotlin.
Несколько слов о Kotlin. У него есть много удобных вещей для Data Science. В совокупности с экосистемой jvm получается «статически типизированный Python на jvm». А не так давно ещё появилась возможность использовать Kotlin вместе с Apache Spark.
Первым делом установим tesseract. Его нужно установить отдельно на систему, согласно описанию из wiki. После установки можно проверить, что tesseract работает следующим образом:
tesseract input_file.jpg stdout -l eng --tessdata-dir /usr/local/share/tessdata/
Где --tessdata-dir — путь до файлов tesseract (/usr/local/share/tessdata/ в macos). В случае успешной установки в stdout будет выведен распознанные текст.
После этого можно подключить tesseract в jvm и сравнить результат работы с нативным вызовом. Для этого подключим библиотеку:
implementation("net.sourceforge.tess4j:tess4j:4.5.3")
Для тех, кто не очень хорошо знаком с экосистемой jvm, есть лёгкий способ быстро себе всё настроить. Понадобится только установленная Java 13+. Её проще всего поставить через sdkman. Далее для удобства можно скачать Intellij IDEA, подойдёт и Community version. Основу проекта можно создать из IDE (new project -> Kotlin, gradle Kotlin) или можно клонировать репозиторий github, в котором перейти на ветку start.
После подключения библиотеки доступ к tesseract становится простым. Вызов той же команды из примера выше будет выглядеть следующим образом:
val api = Tesseract()
api.setDatapath("/usr/local/share/tessdata/")
api.setLanguage("eng")
val image = ImageIO.read(File("input_file.jpg"))
val result: String = api.doOCR(image)
Как видно, практически все команды совпадают с используемыми в вызове из командной строки. Но, как минимум, на macos нужно ещё дополнительно настроить системную переменную jna.library.path, в которую нужно добавить путь до dylib-библиотеки tesseract.
val libPath = "/usr/local/lib"
val libTess = File(libPath, "libtesseract.dylib")
if (libTess.exists()) {
val jnaLibPath = System.getProperty("jna.library.path")
if (jnaLibPath == null) {
System.setProperty("jna.library.path", libPath)
} else {
System.setProperty("jna.library.path", libPath + File.pathSeparator + jnaLibPath)
}
}
После всех настроек можно попробовать запустить распознавание для того же файла и результат должен полностью соответствовать вызову из командной строки.
Перейдём теперь к обработке изображений с OpenCV. В Python для работы с ней не требуется ставить каких-либо дополнительных инструментов, кроме пакета в pip. В описании OpenCV под java указан порядок установки, когда всё ставится отдельно. Для самой jvm-экосистемы подход, когда требуются установки каких-либо нативных библиотек, не совсем привычен. Чаще всего если зависимости требуется какие-либо дополнительные библиотеки, то либо она сама их скачивает (как, например, djl-pytorch), либо при подключении через систему сборки внутри себя уже содержит библиотеки под различные операционные системы. К счастью, для OpenCV есть такая сборка, которой и воспользуемся:
implementation("org.openpnp:opencv:4.3.0-2")
Перед началом работы с OpenCV потребуется подгрузить нативные библиотеки через:
nu.pattern.OpenCV.loadLocally()
После чего можно использовать все доступные инструменты. Как, например, конвертация изображения в чёрно-белый цвет:
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY)
Как вы уже обратили внимание, аргументом для OpenCV выступает Mat, который представляет из себя основной класс-обёртку вокруг изображения в OpenCV в jvm, похожий на привычный BufferedImage.
Сам экземпляр Mat можно получить привычным для Python кода вызовом imread:
val mat = Imgcodecs.imread("input.jpg")
В таком виде экземпляр можно дальше передавать в OpenCV и проделывать с ним различные манипуляции. Но для Java общепринятым является BufferedImage, вокруг которого, как правило, уже может быть выстроен pipeline загрузки и обработки изображения. В связи с чем возникает необходимость конвертации BufferedImage в Mat:
val image: BufferedImage = ...
val pixels = (image.raster.dataBuffer as DataBufferByte).data
val mat = Mat(image.height, image.width, CvType.CV_8UC3)
.apply { put(0, 0, pixels) }
И обратной конвертации Mat в BufferedImage:
val mat = ...
var type = BufferedImage.TYPE_BYTE_GRAY
if (mat.channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR
}
val bufferSize = mat.channels() * mat.cols() * mat.rows()
val b = ByteArray(bufferSize)
mat[0, 0, b] // get all the pixels
val image = BufferedImage(mat.cols(), mat.rows(), type)
val targetPixels = (image.raster.dataBuffer as DataBufferByte).data
System.arraycopy(b, 0, targetPixels, 0, b.size)
В частности, тот же tesseract в методе doOCR поддерживает как файл, так и BufferedImage. Используя вышеописанные преобразования, можно вначале обработать изображения с помощью OpenCV, преобразовать Mat в Bufferedimage и передать подготовленное изображение на вход tesseract.
Попробуем теперь на практике собрать рабочий вариант приложения, который сможет найти текст на следующей картинке:
Для начала проверим результат нахождения текста на изображении без обработки. И вместо метода doOCR будем использовать getWords, чтобы получить ещё confidence (score в Python-библиотеке) для каждого найденного слова:
val image = ImageIO.read(URL("http://img.ifcdn.com/images/b313c1f095336b6d681f75888f8932fc8a531eacd4bc436e4d4aeff7b599b600_1.jpg"))
val result = api.getWords(preparedImage, ITessAPI.TessPageIteratorLevel.RIL_WORD)
В результате будет найден только разный «мусор»:
[ie, [Confidence: 2.014679 Bounding box: 100 0 13 14], bad [Confidence: 61.585358 Bounding box: 202 0 11 14], oy [Confidence: 24.619446 Bounding box: 21 68 18 22], ' [Confidence: 4.998787 Bounding box: 185 40 11 18], | [Confidence: 60.889648 Bounding box: 315 62 4 14], ae. [Confidence: 27.592728 Bounding box: 0 129 320 126], c [Confidence: 0.000000 Bounding box: 74 301 3 2], ai [Confidence: 24.988930 Bounding box: 133 283 41 11], ee [Confidence: 27.483231 Bounding box: 186 283 126 41]]
Если внимательней посмотреть на изображение, то можно увидеть, что шрифт для текста белый, а значит, можно попробовать использовать threshold вместе с последующей инверсией, чтобы оставить текст только на картинке:
Пробуем следующие преобразования:
// convert to gray
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY)
// text -> white, other -> black
Imgproc.threshold(mat, mat, 244.0, 255.0, Imgproc.THRESH_BINARY)
// inverse
Core.bitwise_not(mat, mat)
После них посмотрим на картинку в результате (которую можно сохранить в файл через Imgcodecs.imwrite("output.jpg", mat) )
Теперь если посмотреть на результаты вызова getWords, то получим следующее:
[WHEN [Confidence: 94.933418 Bounding box: 48 251 52 14], SHE [Confidence: 95.249252 Bounding box: 109 251 34 15], CATCHES [Confidence: 95.973259 Bounding box: 151 251 80 15], YOU [Confidence: 96.446579 Bounding box: 238 251 33 15], CHEATING [Confidence: 96.458656 Bounding box: 117 278 86 15]]
Как видно, весь текст успешно распознался.
Итоговый код по обработке изображения будет выглядеть следующим образом:
import net.sourceforge.tess4j.ITessAPI
import net.sourceforge.tess4j.Tesseract
import nu.pattern.OpenCV
import org.opencv.core.Core
import org.opencv.core.CvType
import org.opencv.core.Mat
import org.opencv.imgproc.Imgproc
import java.awt.image.BufferedImage
import java.awt.image.DataBufferByte
import java.io.File
import java.net.URL
import javax.imageio.ImageIO
fun main() {
setupOpenCV()
setupTesseract()
val image = ImageIO.read(URL("http://img.ifcdn.com/images/b313c1f095336b6d681f75888f8932fc8a531eacd4bc436e4d4aeff7b599b600_1.jpg"))
val mat = image.toMat()
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY)
Imgproc.threshold(mat, mat, 244.0, 255.0, Imgproc.THRESH_BINARY)
Core.bitwise_not(mat, mat)
val preparedImage = mat.toBufferedImage()
val api = Tesseract()
api.setDatapath("/usr/local/share/tessdata/")
api.setLanguage("eng")
val result = api.getWords(preparedImage, ITessAPI.TessPageIteratorLevel.RIL_WORD)
println(result)
}
private fun setupTesseract() {
val libPath = "/usr/local/lib"
val libTess = File(libPath, "libtesseract.dylib")
if (libTess.exists()) {
val jnaLibPath = System.getProperty("jna.library.path")
if (jnaLibPath == null) {
System.setProperty("jna.library.path", libPath)
} else {
System.setProperty("jna.library.path", libPath + File.pathSeparator + jnaLibPath)
}
}
}
private fun setupOpenCV() {
OpenCV.loadLocally()
}
private fun BufferedImage.toMat(): Mat {
val pixels = (raster.dataBuffer as DataBufferByte).data
return Mat(height, width, CvType.CV_8UC3)
.apply { put(0, 0, pixels) }
}
private fun Mat.toBufferedImage(): BufferedImage {
var type = BufferedImage.TYPE_BYTE_GRAY
if (channels() > 1) {
type = BufferedImage.TYPE_3BYTE_BGR
}
val bufferSize = channels() * cols() * rows()
val b = ByteArray(bufferSize)
this[0, 0, b] // get all the pixels
val image = BufferedImage(cols(), rows(), type)
val targetPixels = (image.raster.dataBuffer as DataBufferByte).data
System.arraycopy(b, 0, targetPixels, 0, b.size)
return image
}
Если сравнить полученный код с Python-версией, то разница будет минимальная. Производительность тоже должна быть практически сравнимой (за исключением, быть может, чуть больших преобразований изображения между Mat и BufferedImage).
Преимущество Python в рамках текущего примера будет только в бесшовной передаче изображений между OpenCV и tesseract. Экосистема Python сама по себе удобна тем, что все библиотеки общаются одними и теми же типами.
В jvm-экосистеме тоже есть свои преимущества. Это и статическая типизация, и многопоточность, и общая скорость работы вместе с наличием огромного количества инструментов под любые требования. Может, текущий пример не сильно раскрывает все преимущества, но, как минимум, он демонстрирует, что для данной задачи решение на jvm и Kotlin получается ничуть не сложнее.
Python на текущий момент, беcспорно, лидер в ML. И в первую очередь все инструменты и библиотеки появляются на нём. Тем не менее, в других экосистемах можно использовать те же инструменты. Особенно учитывая, что если что-то есть под Python, то должна быть и нативная библиотека, которую можно легко подключить.
Надеюсь, что в этой статье вы нашли для себя что-нибудь полезное и новое. Спасибо за внимание, и напоследок несколько полезных ссылок:
djl.ai — Deep Learning на jvm, где можно подключать модели из pytorch и tensorflow
deeplearning4j.org — аналогичное решение с возможностью обучать модели и импортировать существующие на tensorflow и keras
kotlinlang.org/docs/reference/data-science-overview — разные полезные вещи по Data Science на Kotlin (и Java)
Весь код доступен в репозитории.
===========
Источник:
habr.com
===========
Похожие новости:
- [Производство и разработка электроники, Научно-популярное, Биотехнологии, Здоровье] Нет реальности без боли: электронный эквивалент рецепторов кожи человека
- [JavaScript, ReactJS, VueJS] Микросервисы во фронтенде
- [Big Data, Алгоритмы, Карьера в IT-индустрии, Машинное обучение] Подбор скважин-кандидатов для гидравлического разрыва пласта с использованием методов машинного обучения
- [Расширения для браузеров] Конструктор интерактивных туров
- [IT-эмиграция, Карьера в IT-индустрии] [Личный опыт] Как я переехал в Австралию всего с двумя годами опыта в разработке
- [JavaScript, Node.JS, Разработка веб-сайтов] Компоновщик в JavaScript (перевод)
- [Разработка веб-сайтов, Python, Программирование, C++] Разработка python module, чтобы продакшн радовал
- [JavaScript, Профессиональная литература] TypeScript. Продвинутые типы
- [Производство и разработка электроники, Процессоры] Исследователи продемонстрировали жидкостное охлаждение на чипе
- [Управление проектами, ERP-системы, CRM-системы, Управление разработкой, Финансы в IT] ERP-система: управление показателями на стыке коммерции и IT
Теги для поиска: #_python, #_programmirovanie (Программирование), #_java, #_kotlin, #_razrabotka (разработка), #_programmirovanie (программирование), #_java, #_kotlin, #_python, #_tesseract, #_opencv, #_blog_kompanii_funcorp (
Блог компании FunCorp
), #_python, #_programmirovanie (
Программирование
), #_java, #_kotlin
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:16
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Ни для кого не секрет, что Python прочно занял первенство в ML и Data Science. А что если посмотреть на другие языки и платформы? Насколько в них удобно делать аналогичные решения? К примеру, распознавание текста на картинке. Среди текущих решений одним из наиболее распространённым инструментом является tesseract. В Python для него существует удобная библиотека, а для первоначальной обработки изображений, как правило, используется OpenCV. Для обоих этих инструментов есть исходные C++ библиотеки, поэтому их также возможно вызывать и из других экосистем. Попробуем это сделать в jvm и, в частности, на Kotlin. Несколько слов о Kotlin. У него есть много удобных вещей для Data Science. В совокупности с экосистемой jvm получается «статически типизированный Python на jvm». А не так давно ещё появилась возможность использовать Kotlin вместе с Apache Spark.
tesseract input_file.jpg stdout -l eng --tessdata-dir /usr/local/share/tessdata/
Где --tessdata-dir — путь до файлов tesseract (/usr/local/share/tessdata/ в macos). В случае успешной установки в stdout будет выведен распознанные текст. После этого можно подключить tesseract в jvm и сравнить результат работы с нативным вызовом. Для этого подключим библиотеку: implementation("net.sourceforge.tess4j:tess4j:4.5.3")
Для тех, кто не очень хорошо знаком с экосистемой jvm, есть лёгкий способ быстро себе всё настроить. Понадобится только установленная Java 13+. Её проще всего поставить через sdkman. Далее для удобства можно скачать Intellij IDEA, подойдёт и Community version. Основу проекта можно создать из IDE (new project -> Kotlin, gradle Kotlin) или можно клонировать репозиторий github, в котором перейти на ветку start.
val api = Tesseract()
api.setDatapath("/usr/local/share/tessdata/") api.setLanguage("eng") val image = ImageIO.read(File("input_file.jpg")) val result: String = api.doOCR(image) Как видно, практически все команды совпадают с используемыми в вызове из командной строки. Но, как минимум, на macos нужно ещё дополнительно настроить системную переменную jna.library.path, в которую нужно добавить путь до dylib-библиотеки tesseract. val libPath = "/usr/local/lib"
val libTess = File(libPath, "libtesseract.dylib") if (libTess.exists()) { val jnaLibPath = System.getProperty("jna.library.path") if (jnaLibPath == null) { System.setProperty("jna.library.path", libPath) } else { System.setProperty("jna.library.path", libPath + File.pathSeparator + jnaLibPath) } } После всех настроек можно попробовать запустить распознавание для того же файла и результат должен полностью соответствовать вызову из командной строки. Перейдём теперь к обработке изображений с OpenCV. В Python для работы с ней не требуется ставить каких-либо дополнительных инструментов, кроме пакета в pip. В описании OpenCV под java указан порядок установки, когда всё ставится отдельно. Для самой jvm-экосистемы подход, когда требуются установки каких-либо нативных библиотек, не совсем привычен. Чаще всего если зависимости требуется какие-либо дополнительные библиотеки, то либо она сама их скачивает (как, например, djl-pytorch), либо при подключении через систему сборки внутри себя уже содержит библиотеки под различные операционные системы. К счастью, для OpenCV есть такая сборка, которой и воспользуемся: implementation("org.openpnp:opencv:4.3.0-2")
Перед началом работы с OpenCV потребуется подгрузить нативные библиотеки через: nu.pattern.OpenCV.loadLocally()
После чего можно использовать все доступные инструменты. Как, например, конвертация изображения в чёрно-белый цвет: Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY)
Как вы уже обратили внимание, аргументом для OpenCV выступает Mat, который представляет из себя основной класс-обёртку вокруг изображения в OpenCV в jvm, похожий на привычный BufferedImage. Сам экземпляр Mat можно получить привычным для Python кода вызовом imread: val mat = Imgcodecs.imread("input.jpg")
В таком виде экземпляр можно дальше передавать в OpenCV и проделывать с ним различные манипуляции. Но для Java общепринятым является BufferedImage, вокруг которого, как правило, уже может быть выстроен pipeline загрузки и обработки изображения. В связи с чем возникает необходимость конвертации BufferedImage в Mat: val image: BufferedImage = ...
val pixels = (image.raster.dataBuffer as DataBufferByte).data val mat = Mat(image.height, image.width, CvType.CV_8UC3) .apply { put(0, 0, pixels) } И обратной конвертации Mat в BufferedImage: val mat = ...
var type = BufferedImage.TYPE_BYTE_GRAY if (mat.channels() > 1) { type = BufferedImage.TYPE_3BYTE_BGR } val bufferSize = mat.channels() * mat.cols() * mat.rows() val b = ByteArray(bufferSize) mat[0, 0, b] // get all the pixels val image = BufferedImage(mat.cols(), mat.rows(), type) val targetPixels = (image.raster.dataBuffer as DataBufferByte).data System.arraycopy(b, 0, targetPixels, 0, b.size) В частности, тот же tesseract в методе doOCR поддерживает как файл, так и BufferedImage. Используя вышеописанные преобразования, можно вначале обработать изображения с помощью OpenCV, преобразовать Mat в Bufferedimage и передать подготовленное изображение на вход tesseract. Попробуем теперь на практике собрать рабочий вариант приложения, который сможет найти текст на следующей картинке: Для начала проверим результат нахождения текста на изображении без обработки. И вместо метода doOCR будем использовать getWords, чтобы получить ещё confidence (score в Python-библиотеке) для каждого найденного слова: val image = ImageIO.read(URL("http://img.ifcdn.com/images/b313c1f095336b6d681f75888f8932fc8a531eacd4bc436e4d4aeff7b599b600_1.jpg"))
val result = api.getWords(preparedImage, ITessAPI.TessPageIteratorLevel.RIL_WORD) В результате будет найден только разный «мусор»: [ie, [Confidence: 2.014679 Bounding box: 100 0 13 14], bad [Confidence: 61.585358 Bounding box: 202 0 11 14], oy [Confidence: 24.619446 Bounding box: 21 68 18 22], ' [Confidence: 4.998787 Bounding box: 185 40 11 18], | [Confidence: 60.889648 Bounding box: 315 62 4 14], ae. [Confidence: 27.592728 Bounding box: 0 129 320 126], c [Confidence: 0.000000 Bounding box: 74 301 3 2], ai [Confidence: 24.988930 Bounding box: 133 283 41 11], ee [Confidence: 27.483231 Bounding box: 186 283 126 41]]
Если внимательней посмотреть на изображение, то можно увидеть, что шрифт для текста белый, а значит, можно попробовать использовать threshold вместе с последующей инверсией, чтобы оставить текст только на картинке: Пробуем следующие преобразования: // convert to gray
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY) // text -> white, other -> black Imgproc.threshold(mat, mat, 244.0, 255.0, Imgproc.THRESH_BINARY) // inverse Core.bitwise_not(mat, mat) После них посмотрим на картинку в результате (которую можно сохранить в файл через Imgcodecs.imwrite("output.jpg", mat) ) Теперь если посмотреть на результаты вызова getWords, то получим следующее: [WHEN [Confidence: 94.933418 Bounding box: 48 251 52 14], SHE [Confidence: 95.249252 Bounding box: 109 251 34 15], CATCHES [Confidence: 95.973259 Bounding box: 151 251 80 15], YOU [Confidence: 96.446579 Bounding box: 238 251 33 15], CHEATING [Confidence: 96.458656 Bounding box: 117 278 86 15]]
Как видно, весь текст успешно распознался. Итоговый код по обработке изображения будет выглядеть следующим образом: import net.sourceforge.tess4j.ITessAPI
import net.sourceforge.tess4j.Tesseract import nu.pattern.OpenCV import org.opencv.core.Core import org.opencv.core.CvType import org.opencv.core.Mat import org.opencv.imgproc.Imgproc import java.awt.image.BufferedImage import java.awt.image.DataBufferByte import java.io.File import java.net.URL import javax.imageio.ImageIO fun main() { setupOpenCV() setupTesseract() val image = ImageIO.read(URL("http://img.ifcdn.com/images/b313c1f095336b6d681f75888f8932fc8a531eacd4bc436e4d4aeff7b599b600_1.jpg")) val mat = image.toMat() Imgproc.cvtColor(mat, mat, Imgproc.COLOR_BGR2GRAY) Imgproc.threshold(mat, mat, 244.0, 255.0, Imgproc.THRESH_BINARY) Core.bitwise_not(mat, mat) val preparedImage = mat.toBufferedImage() val api = Tesseract() api.setDatapath("/usr/local/share/tessdata/") api.setLanguage("eng") val result = api.getWords(preparedImage, ITessAPI.TessPageIteratorLevel.RIL_WORD) println(result) } private fun setupTesseract() { val libPath = "/usr/local/lib" val libTess = File(libPath, "libtesseract.dylib") if (libTess.exists()) { val jnaLibPath = System.getProperty("jna.library.path") if (jnaLibPath == null) { System.setProperty("jna.library.path", libPath) } else { System.setProperty("jna.library.path", libPath + File.pathSeparator + jnaLibPath) } } } private fun setupOpenCV() { OpenCV.loadLocally() } private fun BufferedImage.toMat(): Mat { val pixels = (raster.dataBuffer as DataBufferByte).data return Mat(height, width, CvType.CV_8UC3) .apply { put(0, 0, pixels) } } private fun Mat.toBufferedImage(): BufferedImage { var type = BufferedImage.TYPE_BYTE_GRAY if (channels() > 1) { type = BufferedImage.TYPE_3BYTE_BGR } val bufferSize = channels() * cols() * rows() val b = ByteArray(bufferSize) this[0, 0, b] // get all the pixels val image = BufferedImage(cols(), rows(), type) val targetPixels = (image.raster.dataBuffer as DataBufferByte).data System.arraycopy(b, 0, targetPixels, 0, b.size) return image } Если сравнить полученный код с Python-версией, то разница будет минимальная. Производительность тоже должна быть практически сравнимой (за исключением, быть может, чуть больших преобразований изображения между Mat и BufferedImage). Преимущество Python в рамках текущего примера будет только в бесшовной передаче изображений между OpenCV и tesseract. Экосистема Python сама по себе удобна тем, что все библиотеки общаются одними и теми же типами. В jvm-экосистеме тоже есть свои преимущества. Это и статическая типизация, и многопоточность, и общая скорость работы вместе с наличием огромного количества инструментов под любые требования. Может, текущий пример не сильно раскрывает все преимущества, но, как минимум, он демонстрирует, что для данной задачи решение на jvm и Kotlin получается ничуть не сложнее. Python на текущий момент, беcспорно, лидер в ML. И в первую очередь все инструменты и библиотеки появляются на нём. Тем не менее, в других экосистемах можно использовать те же инструменты. Особенно учитывая, что если что-то есть под Python, то должна быть и нативная библиотека, которую можно легко подключить. Надеюсь, что в этой статье вы нашли для себя что-нибудь полезное и новое. Спасибо за внимание, и напоследок несколько полезных ссылок: djl.ai — Deep Learning на jvm, где можно подключать модели из pytorch и tensorflow deeplearning4j.org — аналогичное решение с возможностью обучать модели и импортировать существующие на tensorflow и keras kotlinlang.org/docs/reference/data-science-overview — разные полезные вещи по Data Science на Kotlin (и Java) Весь код доступен в репозитории. =========== Источник: habr.com =========== Похожие новости:
Блог компании FunCorp ), #_python, #_programmirovanie ( Программирование ), #_java, #_kotlin |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:16
Часовой пояс: UTC + 5