Что нового

Извлечение из растровой картинки - диаграммы.

RipVanWinkel

Новичок
Сообщения
81
Репутация
0
Здравствуйте, хочу задать необычный вопрос.

В файле-картинке имеются таблицы, какой-то текст и график.
Может ли autoit-скрипт понять где находится график и извлечь его из этого файла - в отдельный файл-изображение ?

(Человек может понять где - что находится - где таблица, а где график или где текст)
А как для это скрипта хотя бы теоретически это сформулировать ?
 

Вложения

  • Рисунок.jpg
    Рисунок.jpg
    108.2 КБ · Просмотры: 7

Medic84

Омега
Команда форума
Администратор
Сообщения
1,590
Репутация
341
Цвета, расположение графика относительно страницы - меняются? Размеры страницы? Если меняются, то скорее всего - это надо в машинное зрение, об этом хорошо рассказывает @Belfigor в теме http://autoit-script.ru/threads/vve...ota-s-nejrosetjami-dlja-samyx-malenkix.26826/
Но это нейросети и обучение. А если не меняется, то может просто по координатам вырезать и все.
 

Belfigor

Модератор
Локальный модератор
Сообщения
3,608
Репутация
941
Если картинка фиксированных размеров и с явной рамкой то можно просто искать всё подходящее по размерам. Если машинное обучение - то это свёрточные сети и придётся при любом раскладе использовать внешние библиотеки. Любая нейросеть реализованная на чистом автоит - будет работать очень медленно. Но тут нет ничего удивительного, те же самые библиотеки используемые в питоне по факту реализованы на сях и асме и просто смотрят наружу питоновскими апишечками.
 
Автор
R

RipVanWinkel

Новичок
Сообщения
81
Репутация
0
График может быть разного размера и стоять в разных местах.
А если он будет всегда очерчен - зеленой рамкой - тогда можно его извлечь ?
 

Вложения

  • Рисунок - 2.jpg
    Рисунок - 2.jpg
    113.8 КБ · Просмотры: 7

ZaRaki

Знающий
Сообщения
48
Репутация
19
Да, тогда можно.
В примере ниже, $color это цвет рамки, шестнадцатеричный формат.
$mainimg - изображение для поиска графика (формат .jpg или .bmp)
$grafickimg - сохранение графика в файл (формат .jpg или .bmp)
Пример написан так, что не важно какого размера будет изначально файл, в функцию уже вписан ресайзер, который подгонит под размеры окна. Главное чтоб график был обведён рамкой. Цвет для рамки выбери супер индвидуальный какой-нить, типо светлорозовый что ли я хз ))
.
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <File.au3>
#include <ScreenCapture.au3>

Opt("PixelCoordMode", 2)

global $color = 'ed1b24'
global $mainimg = @ScriptDir & "\sss.jpg"
global $grafickimg = @ScriptDir & "\ddd.jpg"

   _GDIPlus_Startup()
   $hBitmap = _GDIPlus_BitmapCreateFromFile($mainimg)
   $img_w = _GDIPlus_ImageGetWidth($hBitmap)
   $img_y = _GDIPlus_ImageGetHeight($hBitmap)
   _GDIPlus_BitmapDispose($hBitmap)
   _GDIPlus_Shutdown()

   $gui_w = @desktopwidth-60
   $gui_y = @DesktopHeight-100
   $normalize_w = $img_w/$gui_w
   $normalize_y = $img_y/$gui_y
   if($img_y/$normalize_w < $gui_y) Then
      $total_w = $gui_w
      $total_y = $img_y/$normalize_w
   Else
      $total_w = $img_w/$normalize_y
      $total_y = $gui_y
   EndIf

   $hgui = GUICreate($mainimg, $gui_w, $gui_y, -1, -1, $WS_POPUP) ; Создаёт окно в центре экрана
   $hImage = GUICtrlCreatePic($mainimg, 0, 0, $total_w, $total_y)
   GUICtrlSetState(-1, $GUI_DISABLE)
   GUISetState()

WinWaitActive($hgui)
sleep(250)
            $pixel_left_top_coords = PixelSearch(0, 0, $gui_w, $gui_y,'0x' & $color,0,5,$hgui)
            if @error <> 1 Then
               $pixel_right_top_coords = PixelSearch($gui_w, $pixel_left_top_coords[1], $pixel_left_top_coords[0], $pixel_left_top_coords[1],'0x' & $color,0,5,$hgui)
               $pixel_left_bottom_coords = PixelSearch(0, $gui_y, $gui_w, 0,'0x' & $color,0,5,$hgui)
               $pixel_right_bottom_coords = PixelSearch($gui_w, $pixel_left_bottom_coords[1], $pixel_left_bottom_coords[0], $pixel_left_top_coords[1],'0x' & $color,0,5,$hgui)

               _ScreenCapture_CaptureWnd($grafickimg, $hgui, $pixel_left_top_coords[0]-5, $pixel_left_top_coords[1]-5, $pixel_right_bottom_coords[0]+5, $pixel_right_bottom_coords[1]+5, False)
            Else
               msgbox(0,"","рамка вокруг графика не найдена")
            EndIf

   GUIDelete()
 
Автор
R

RipVanWinkel

Новичок
Сообщения
81
Репутация
0
ZaRaki
Понятно.
Выставил цветовой код в скрипте - global $color = '0x21B14E'
Но почему-то выводится в ddd.jpg - не только один график, а еще куча всего лишнего - рамка, какой-то текст внизу, таблица (также добавляется пустое место с правой стороны рисунка).

Нужно только то, что находится внутри рамки (саму зеленую рамку извлекать не нужно).
 

ZaRaki

Знающий
Сообщения
48
Репутация
19
ZaRaki
Понятно.
Выставил цветовой код в скрипте - global $color = '0x21B14E'
Но почему-то выводится в ddd.jpg - не только один график, а еще куча всего лишнего - рамка, какой-то текст внизу, таблица (также добавляется пустое место с правой стороны рисунка).

Нужно только то, что находится внутри рамки (саму зеленую рамку извлекать не нужно).
А зачем вы обозначили цвет в виде 0x21B14E ??
Укажите просто сам цвет '21B14E'
Саму рамку делать толстой не обязательно, достаточно и 2,3,4 пикселя
 
Автор
R

RipVanWinkel

Новичок
Сообщения
81
Репутация
0
ZaRaki
Заменил.

Но по-прежнему происходит все в точности - то же самое.
То есть - выводится в ddd.jpg - не только один график, а еще куча всего лишнего - рамка, текст внизу, таблица, и пустое место с правой стороны рисунка.

А зачем вы обозначили цвет в виде 0x21B14E ??
Иначе скрипт выдает сообщение "Рамка вокруг графика не найдена".
 

ZaRaki

Знающий
Сообщения
48
Репутация
19
ZaRaki
Заменил.

Но по-прежнему происходит все в точности - то же самое.
То есть - выводится в ddd.jpg - не только один график, а еще куча всего лишнего - рамка, текст внизу, таблица, и пустое место с правой стороны рисунка.


Иначе скрипт выдает сообщение "Рамка вокруг графика не найдена".
Дело в том, что цвет 0х0x21B14E не существует ))
Выше в примере я уже применяю префикс 0х в 39 строке.
А у вас получается он пытается найти несуществующий цвет.
Или выведите свой код, как вы его переделали в итоге? Так думаю проще будет.
 
Автор
R

RipVanWinkel

Новичок
Сообщения
81
Репутация
0
Да тот же самый код по сути, только с обозначением цвета:
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <File.au3>
#include <ScreenCapture.au3>

Opt("PixelCoordMode", 2)

global $color = '0x21B14E'
global $mainimg = @ScriptDir & "\sss.jpg"
global $grafickimg = @ScriptDir & "\ddd.jpg"

   _GDIPlus_Startup()
   $hBitmap = _GDIPlus_BitmapCreateFromFile($mainimg)
   $img_w = _GDIPlus_ImageGetWidth($hBitmap)
   $img_y = _GDIPlus_ImageGetHeight($hBitmap)
   _GDIPlus_BitmapDispose($hBitmap)
   _GDIPlus_Shutdown()

   $gui_w = @desktopwidth-60
   $gui_y = @DesktopHeight-100
   $normalize_w = $img_w/$gui_w
   $normalize_y = $img_y/$gui_y
   if($img_y/$normalize_w < $gui_y) Then
      $total_w = $gui_w
      $total_y = $img_y/$normalize_w
   Else
      $total_w = $img_w/$normalize_y
      $total_y = $gui_y
   EndIf

   $hgui = GUICreate($mainimg, $gui_w, $gui_y, -1, -1, $WS_POPUP) ; Создаёт окно в центре экрана
   $hImage = GUICtrlCreatePic($mainimg, 0, 0, $total_w, $total_y)
   GUICtrlSetState(-1, $GUI_DISABLE)
   GUISetState()

WinWaitActive($hgui)
sleep(250)
            $pixel_left_top_coords = PixelSearch(0, 0, $gui_w, $gui_y,'0x' & $color,0,5,$hgui)
            if @error <> 1 Then
               $pixel_right_top_coords = PixelSearch($gui_w, $pixel_left_top_coords[1], $pixel_left_top_coords[0], $pixel_left_top_coords[1],'0x' & $color,0,5,$hgui)
               $pixel_left_bottom_coords = PixelSearch(0, $gui_y, $gui_w, 0,'0x' & $color,0,5,$hgui)
               $pixel_right_bottom_coords = PixelSearch($gui_w, $pixel_left_bottom_coords[1], $pixel_left_bottom_coords[0], $pixel_left_top_coords[1],'0x' & $color,0,5,$hgui)

               _ScreenCapture_CaptureWnd($grafickimg, $hgui, $pixel_left_top_coords[0]+5, $pixel_left_top_coords[1]+5, $pixel_right_bottom_coords[0]-5, $pixel_right_bottom_coords[1]-5, False)
            Else
               msgbox(0,"","рамка вокруг графика не найдена")
            EndIf

   GUIDelete()
 

ZaRaki

Знающий
Сообщения
48
Репутация
19
Видимо там разница есть в пару битов по цвету.
Увеличил разницу между цветом в 10 шагов.
Вот с применением вашего цвета.
Код:
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
#include <File.au3>
#include <ScreenCapture.au3>

Opt("PixelCoordMode", 2)

global $color = '21b14e'
global $mainimg = @ScriptDir & "\sss.jpg"
global $grafickimg = @ScriptDir & "\ddd.jpg"

   _GDIPlus_Startup()
   $hBitmap = _GDIPlus_BitmapCreateFromFile($mainimg)
   $img_w = _GDIPlus_ImageGetWidth($hBitmap)
   $img_y = _GDIPlus_ImageGetHeight($hBitmap)
   _GDIPlus_BitmapDispose($hBitmap)
   _GDIPlus_Shutdown()

   $gui_w = @desktopwidth-60
   $gui_y = @DesktopHeight-100
   $normalize_w = $img_w/$gui_w
   $normalize_y = $img_y/$gui_y
   if($img_y/$normalize_w < $gui_y) Then
      $total_w = $gui_w
      $total_y = $img_y/$normalize_w
   Else
      $total_w = $img_w/$normalize_y
      $total_y = $gui_y
   EndIf

   $hgui = GUICreate($mainimg, $gui_w, $gui_y, -1, -1, $WS_POPUP) ; Создаёт окно в центре экрана
   $hImage = GUICtrlCreatePic($mainimg, 0, 0, $total_w, $total_y)
   GUICtrlSetState(-1, $GUI_DISABLE)
   GUISetState()

WinWaitActive($hgui)
sleep(250)
            $pixel_left_top_coords = PixelSearch(0, 0, $gui_w, $gui_y,'0x' & $color,10,5,$hgui)
            if @error <> 1 Then
               $pixel_right_top_coords = PixelSearch($gui_w, $pixel_left_top_coords[1], $pixel_left_top_coords[0], $pixel_left_top_coords[1],'0x' & $color,10,5,$hgui)
               $pixel_left_bottom_coords = PixelSearch(0, $gui_y, $gui_w, 0,'0x' & $color,10,5,$hgui)
               $pixel_right_bottom_coords = PixelSearch($gui_w, $pixel_left_bottom_coords[1], $pixel_left_bottom_coords[0], $pixel_left_top_coords[1],'0x' & $color,10,5,$hgui)

               _ScreenCapture_CaptureWnd($grafickimg, $hgui, $pixel_left_top_coords[0]+15, $pixel_left_top_coords[1]+15, $pixel_right_bottom_coords[0]-15, $pixel_right_bottom_coords[1]-15, False)
            Else
               msgbox(0,"","рамка вокруг графика не найдена")
            EndIf

   GUIDelete()

Сообщение автоматически объединено:

Да тот же самый код по сути, только с обозначением цвета:
По поводу самой рамки, то не делать слишком толстой, для 1920х1080 экрана примерно 2-7 пикселя толщина вполне оптимально, тогда рамку не должно быть видно. Так же в идеале будет если между маркой и графиком будет пустое белое пространство хотябы пикселей 10. Потому что в новом коде я обрезаю внутренюю часть примерно на 10 пикселей по краям, чтоб рамку не было видно.
 
Автор
R

RipVanWinkel

Новичок
Сообщения
81
Репутация
0
ZaRaki
Спасибо. Уже намного лучше.

Но скрипт сейчас слишком много убирает внутри зеленой рамки.
Например в данном случае - он полностью удалил те части где идут наименования осей графика - буквы b и a.
 

Вложения

  • ddd.jpg
    ddd.jpg
    35 КБ · Просмотры: 3

ZaRaki

Знающий
Сообщения
48
Репутация
19
ZaRaki
Спасибо. Уже намного лучше.

Но скрипт сейчас слишком много убирает внутри зеленой рамки.
Например в данном случае - он полностью удалил те части где идут наименования осей графика - буквы b и a.
Я же написал, не делай обводку вплотную к графику, сделай немного пустого пространства. Я специально обрезаю 10 пикселей чтоб рамки не было видно.
 

Вложения

  • Рисунок.jpg
    Рисунок.jpg
    267.7 КБ · Просмотры: 4
  • Рисунок2.jpg
    Рисунок2.jpg
    235.6 КБ · Просмотры: 5
Автор
R

RipVanWinkel

Новичок
Сообщения
81
Репутация
0
ZaRaki
Теперь понятно.
Я подогнал сколько нужно пикселей.

Спасибо за ответ.
Теперь все нормально работает.
 
Верх