Русский
Русский
English
Статистика
Реклама

Урок

GOMS-анализ юзабилити интерфейса

28.07.2020 12:21:05 | Автор: admin
image

Данная статья практически полностью основана на цитатах из книги Джефа Раскина Интерфейс новые направления в проектировании компьютерных систем с моими дополнениями и воссозданием приводимого в книге примера интерфейса.

Быстрый ответ на вопрос стоит ли использовать GOMS-анализ для проверки юзабилити: Если вы проектируете интерфейс, при работе с которым от задержки в 0,3 сек. никто не умирает не стоит..

Итак, The model of Goals, Objects, Methods, and Selection rules (GOMS) это метод исследования интерфейса, разработанный Кардом, Мораном и Ньюэллом в 80-х годах. GOMS позволяет предсказать, сколько времени потребуется опытному (именно опытному) пользователю на выполнение конкретной операции при использовании конкретного интерфейса.

Теперь, когда мы привыкли к этому странному для русского уха термину, можно описать его суть.

Разработчики GOMS заметили, что время на выполнение какой-то задачи пользователем, равно сумме всех временных интервалов, которые потребовались на выполнение каждого конкретного жеста пользователя (например, переместить руку с мыши на клавиатуру и набрать букву). С помощью лабораторных исследований был получен набор временных интервалов, требуемых для выполнения различных жестов.

Жесты и время по модели GOMS:


  1. H (перенос руки на мышь) = 0,4 сек
  2. К (нажатие клавиши клавиатуры или мыши) = 0,2 сек
  3. Р (перенос курсора к позиции на экране) = 1,1 сек
  4. М (обдумывание следующего шага) = 1,35 сек
  5. R (ожидание ответа системы) время зависит от быстродействия конкретной системы и не участвует в расчётах.


В дальнейших расчётах Жесты будут заменяться буквенными обозначениями из списка выше и будут называться Операторы.

Ниже пойдут довольно замысловатые правила работы с этими самыми жестами (операторами). Пока просто прочитайте их, а дальше я всё объясню на примере.

Правила расстановки операторов:


  • Правило 0. Начальная расстановка операторов M
    Операторы M надо ставить перед всеми операторами K (нажатие клавиши), а также перед всеми операторами P (указание с помощью мыши), предназначенными для выбора команд (например, указание на выпадающий список); но перед операторами P, предназначенными для указания на аргументы этих команд (например, конкретный пункт в выпавшем списке), ставить оператор M не надо.
  • Правило 1. Удаление ожидаемых операторов M
    Если оператор, следующий за оператором M, является полностью ожидаемым с точки зрения оператора, предшествующего M, то этот оператор M может быть удален. Например, если вы перемещаете мышь чтобы нажать кнопку по достижении цели, то в соответствии с этим правилом следует удалить оператор M, устанавливаемый по правилу 0.
  • Правило 2. Удаление операторов M внутри когнитивных единиц
    Если строка вида M K M K M K принадлежит когнитивной единице, то следует удалить все операторы M, кроме первого. Когнитивной единицей является непрерывная последовательность вводимых символов, например 4564.23 или Константин Константинопольский.
  • Правило 3. Удаление операторов M перед последовательными разделителями
    Если оператор K означает разделитель, стоящий в конце когнитивной единицы (например, тире между двумя днями понедельник четверг), то следует удалить оператор M, стоящий перед ним.
  • Правило 4. Удаление операторов M, которые являются прерывателями команд
    Если оператор K является разделителем, стоящим после постоянной строки (например, точка в конце предложения, которая каждый раз вводится в неизменном виде), то следует удалить оператор M, стоящий перед ним. Добавление разделителя станет привычным действием, и поэтому разделитель станет частью строки и не будет требовать специального оператора M. Но если оператор K является разделителем для строки аргументов или любой другой изменяемой строки, то оператор M следует сохранить перед ним.
  • Правило 5. Удаление перекрывающих операторов M
    Любую часть оператора M, которая перекрывает оператор R, означающий задержку, связанную с ожиданием ответа компьютера, учитывать не следует.


Применение метода


Дано:
Юзера просят перевести температуру из Фаренгейта в Цельсий или наоборот. Например, могут попросить: Переведи, 3,5 градуса по Фаренгейту в градусы по Цельсию. Значение температуры юзер может ввести только с помощью клавиатуры или мыши.

Задача:
Спроектировать интерфейс, где время на перевод значений температуры минимально.

Условия
Для простоты, будем считать, что юзер вводит значения максимум из двух символов и юзер не совершает ошибок.

Важно: Приведённые ниже примеры служат именно для иллюстрации правил описанных в книге. Решить эту задачу можно было и другими, возможно более оптимальными, способами.

Решение. Вариант 1


Представим, что юзер сначала должен понять в какую сторону произойдёт перевод и если в нужную ему сторону, то просто вводит цифры. Если в не нужную сторону, то он переключается в радио-группе на нужную.



Расчёт:


Н (руку на мышь) + М (думаем) + Р (ведём курсор к радио-группе) + К (клик) + М (думаем) + Р (курсор к полю) + К (клик) + Н (перенос руки с мыши на клаву) + М (думаем) + К (ввод первой цифры) + М (думаем) + К (ввод второй цифры).

По правилу 2, удаляем лишние М и получаем:
Н + М + Р + К + М + Р + К + Н + М + К + К

Если выбрано НЕ подходящее направление конвертации температур, то получаем:
0,4 + 1,35 + 1,1 + 0,2 + 1,35 + 1,1 + 0,2 + 0,4 + 1,35 + 0,2 + 0,2 = 7,85 сек

Если выбрано подходящее направление конвертации температур, то получаем:
0,4 + 1,35 + 1,1 + 0,2 + 1,35 + 0,2 + 0,2 = 4,8 сек

Решение. Вариант 2


Выпиливаем необходимость переключать сторону перевода значений. Делаем поля ввода перетаскиваемыми. Если меняем положение / значение одного поля, то автоматически меняется и положение / значение другого.



Расчёт:


Н (0,4) + М (1,35) + Р (1,1) + К (0,2) + Р (1,1) = 4,15 сек

Этот вариант реализации юзабельней первого на 0,65 сек.

Погрешность метода


Раскин пишет, что с помощью этого метода можно предсказать, сколько времени понадобится пользователю на его задачи с абсолютной погрешностью менее 5%.

Также, не стоит считать, что этим методом мы измерили конкретное время работы с интерфейсом. Это странно, ведь, по сути мы именно это и сделали, но надо понимать, что секунды использованы больше как некая условность. Ведь, у разных юзеров может быть разная скорость работы. Просто нам нужно было понять насколько конкретно один интерфейс юзабельней другого и единицы измерения нам в этом помогли. Реальная скорость работы может совпадать с нашими ожиданиями, а может и не совпадать всё будет зависеть от конкретного юзера.

Моё мнение о GOMS анализе


Когда я только узнал о нём мне захотелось немедленно начать его использовать во всех своих проектах. Мне казалось, что вот оно избавление от извечных мук выбора как правильней. Без субъективщины и трендов. Реальная тупая математика. Но на деле, чтобы описать даже самый примитивный интерфейс, надо потратить раза в два больше времени чем на его проектирование. А потом всё равно придётся спроектировать альтернативный вариант чтобы посчитать и его. И даже если в итоге я узнаю какой вариант лучше, окажется, что он лучше на 0,65 сек. Потратить 34 часа чтобы выиграть 0,65 сек это мощно.
Тем не менее я, считаю, что метод всё равно классный и его стоит использовать, но в каких-то супер важных интерфейсах в которых даже 0,65 сек имеют значение. В большинстве же проектов логичней положиться на свой опыт и постфактум просто спросить юзеров, как им удобнее.

Раскин примерно так и пишет:
Разработчики, которые знакомы с методом GOMS, редко проводят детальный и формальный анализ модели интерфейса. Отчасти это происходит из-за того, что основы GOMS и других количественных методов известны им настолько, что они изначально руководствуются этими методами в процессе разработки.


P. S.


Существуют и модификации GOMS анализа. Например, Сritical-path method GOMS (CPM-GOMS) и версия, называемая естественным языком GOMS (natural GOMS language, NGOMSL) в которой учитывается поведение неопытного пользователя, например время, необходимое ему для обучения. Об этих версиях вы можете прочитать самостоятельно.
Подробнее..

Распознание блоков текста в IOS-приложении с помощью Vision

18.02.2021 14:23:54 | Автор: admin

Работая над приложением, связанным с финансовыми операциями, возникла необходимость распознать и выделить суммы на чеках. Начиная с 13-ой версии в IOS-разработке появился нативный фреймворк Vision, который позволяет распознавать различные объекты на изображениях, без задействования сторонних сервисов.
В данной статье представлен личный опыт разработки приложения, использующего Vision.

Что такое Vision

Из документации Apple: "Vision применяет алгоритмы "компьютерного зрения" для выполнения множества задач с входными изображениями и видео. Фреймворк Vision выполняет распознание лиц, обнаружение текста, распознавание штрих-кодов, регистрацию изображений. Vision также позволяет использовать пользовательские модели CoreML для таких задач, как классификация или обнаружение объектов."
Анализируя документацию Apple, можно предположить, что Vision - это один из этапов подготовки таких продуктов как Apple glasses или шлем смешанной реальности. Забегая вперед, следует подчеркнуть, что данный фреймворк потребляет изрядное количество ресурсов. Обработка статичного изображения может занимать десятки секунд, следовательно, работа с видео в реальном времени будет предельно ресурсоемким процессом, над оптимизацией которого инженерам Apple еще предстоит поработать.
В рамках поставленной задачи, необходимо было решить следующую проблему: распознание блоков текста с помощью Vision.

Разработка

Проект построен на UIKit, который в данной статье детально рассматриваться не будет. Основное внимание уделяется блокам кода, связанным с фреймворком Vision. Приведенные листинги снабжены комментариями, позволяющими разработчикам детальнее понять принцип работы с фреймворком.
В MainViewController, который будет взаимодействовать с фреймворком Vision, нужно объявить две переменные:

//Recognition queuelet textRecognitionWorkQueue = DispatchQueue(label: "TextRecognitionQueue", qos: .userInitiated, attributes: [], autoreleaseFrequency: .workItem)//Request for text recognitionvar textRecognitionRequest: VNRecognizeTextRequest?
  1. Очередь для задач Vision не вызывает никаких затруднений у разработчиков. Именно в ней будут выполняться все задачи фреймворка.

  2. Объявляется переменная типа VNRecognizeTextRequet. Инициализируется объект из ViewDidLoad (или из init), так как он должен быть активен на протяжении всей жизни ViewController. Этот объект отвечает за работу с Vision, поэтому необходимо разобрать его инициализацию подробнее:

//Set textRecognitionRequest from ViewDidLoadfunc setTextRequest() {    textRecognitionRequest = VNRecognizeTextRequest { request, error in        guard let observations = request.results as? [VNRecognizedTextObservation] else {            return        }        var detectedText = ""        self.textBlocks.removeAll()                    for observation in observations {            guard let topCandidate = observation.topCandidates(1).first else { continue }            detectedText += "\(topCandidate.string)\n"                        //Text block specific for this project            if let recognizedBlock = self.getRecognizedDoubleBlock(topCandidate: topCandidate.string, observationBox: observation.boundingBox) {                self.textBlocks.append(recognizedBlock)            }        }                    DispatchQueue.main.async {            self.textView.text = detectedText            self.removeLoader()            self.drawRecognizedBlocks()        }    }            //Individual recognition request settings    textRecognitionRequest!.minimumTextHeight = 0.011 // Lower = better quality    textRecognitionRequest!.recognitionLevel = .accurate}

Настройки объекта textRecognitionRequest. Описание всех доступных настроек можно найти в документации. Наиболее важным является параметр minimumTextHeight. Именно этот параметр отвечает за сочетание быстродействия и точности распознания текста. Для каждого проекта необходимо найти индивидуальное значение данного параметра, оно зависит от того, какие данные будет обрабатывать приложение.
Так как основной поставленной задачей являлось считывание текста с квитанций, для вычисления значения параметра minimumTextHeight в приложение были добавлены различные типы квитанций в различном состоянии (в том числе и основательно помятые). В результате тестирования было определено значение равное 0.011. В случае распознания текста с квитанций, это значение лучшим образом сочетает в себе быстродействие и точность. Однако нужно отметить, что текст с одного изображения распознается в среднем за пять секунд. Подобной скорости недостаточно для обработки информации в реальном времени и ее следует значительно оптимизировать инженерам Apple.
На основе представленного кода можно сделать вывод, что после операции распознания, объект типа VNRecognizeTextRequet получает блоки текста. Именно с ними и ведется дальнейшая работа, в зависимости от функций приложения. В рассматриваемом примере, каждый распознанный фрагмент текста был внесен в текстовое поле. Так как особенностью задействованного приложения является выделение суммы на квитанции, следовательно, сохранялись только блоки текста, которые можно преобразовать в тип Double. Помимо распознанного текстового значения сохраняются и координаты блока текста на изображении.
Представленный ниже метод отвечает за запуск работы запроса на распознание:

//Call text recognition request handlerfunc recognizeImage(cgImage: CGImage) {    textRecognitionWorkQueue.async {        let requestHandler = VNImageRequestHandler(cgImage: cgImage, options: [:])        do {            try requestHandler.perform([self.textRecognitionRequest!])        } catch {            DispatchQueue.main.async {                self.removeLoader()                print(error)            }        }    }}

В метод передается объект CGImage, в котором необходимо распознать текст. Вся работа по распознанию ведется в созданной для этого очереди. Создается объект VNImageRequestHandler, в который передается распознаваемый объект CGImage. В блоке do/try/catch запускается работа инициализированного объекта типа VNRecognizeTextRequet.
Описанные выше функции отвечают за распознание текста в приложении. Однако стоит еще остановится на методах, связанных с выделением нужных блоков текста.

func drawRecognizedBlocks() {    guard let image = invoiceImage?.image else  { return }        //transform from documentation    let imageTransform = CGAffineTransform.identity.scaledBy(x: 1, y: -1).translatedBy(x: 0, y: -image.size.height).scaledBy(x: image.size.width, y: image.size.height)            //drawing rects on cgimage    UIGraphicsBeginImageContextWithOptions(image.size, false, 1.0)    let context = UIGraphicsGetCurrentContext()!    image.draw(in: CGRect(origin: .zero, size: image.size))    context.setStrokeColor(CGColor(srgbRed: 1, green: 0, blue: 0, alpha: 1))    context.setLineWidth(4)        for index in 0 ..< textBlocks.count {        let optimizedRect = textBlocks[index].recognizedRect.applying(imageTransform)        context.addRect(optimizedRect)        textBlocks[index].imageRect = optimizedRect    }    context.strokePath()            let result = UIGraphicsGetImageFromCurrentImageContext()    UIGraphicsEndImageContext()    invoiceImage?.image = result}

В данной статье рисование на изображении не рассматривается, так как при работе с разделом рисование у разработчиков не возникает никаких трудностей. При этом, стоит обратить внимание на особенности работы с координатами распознанных блоков текста. Для сохранения необходимых данных была использована следующая структура:

struct RecognizedTextBlock {    let doubleValue: Double    let recognizedRect: CGRect    var imageRect: CGRect = .zero}

При распознании блоков текста фреймворк Vision вычисляет ряд важных параметров в объекте VNRecognizedTextObservation. Для нужд рассматриваемого проекта необходимо было получить только значение типа Double и его координаты на изображении, сохраняемые в константе recognizedRect.
Для выделения блока текста на изображении, следует применить трансформацию к координатам из константы recognizedRect. Полученные координаты так же сохраняются в объекте RecognizedTextBlock в переменной imageRect, необходимой для обработки нажатий на выделенные блоки текста.
После сохранения точных координат выделяемых блоков на изображении, обработку нажатий на выделенные области можно осуществить несколькими способами:

  • Добавить необходимое количество невидимых кнопок на изображение, при помощи трансформации сохраненного объекта imageRect;

  • При каждом нажатии на изображение проверять массив блоков текста и искать совпадение координат нажатия с сохраненным объектом imageRect и др.

Чтобы не перегружать ViewController дополнительными элементами, был использован второй способ.

//UIImageView tap listener@objc func onImageViewTap(sender: UITapGestureRecognizer) {    guard let invoiceImage = invoiceImage, let image = invoiceImage.image else {        return    }            //get tap coordinates on image    let tapX = sender.location(in: invoiceImage).x    let tapY = sender.location(in: invoiceImage).y    let xRatio = image.size.width / invoiceImage.bounds.width    let yRatio = image.size.height / invoiceImage.bounds.height    let imageXPoint = tapX * xRatio    let imageYPoint = tapY * yRatio    //detecting if one of text blocks tapped    for block in textBlocks {        if block.imageRect.contains(CGPoint(x: imageXPoint, y: imageYPoint)) {            showTapAlert(doubleValue: block.doubleValue)            break        }    }}

Использование представленного метода позволяет вычислить координаты нажатия на объект ImageView с сохранением его пропорций и поиска полученных координат в массиве сохранных распознанных блоков текста.

Выводы

Представленная статья позволяет разработчикам IOS-приложений ознакомиться с фреймворком Vision, прежде всего с его функцией распознания текста. Тестовое приложение, полученное в результате работы с распознанием текста в Vision, является ключом к пониманию работы с такими возможностями фреймворка как распознание лиц, текста, штрих-кодов и др.
Cкриншоты полученного приложения для распознавания цифровых значений на различных изображениях представлены ниже:

Приложение распознающее блоки текста с помощью VisionПриложение распознающее блоки текста с помощью Vision

Для ознакомления проект можно скачать из репозитория.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru