<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Tutorials - Inero Software - Software Consulting</title>
	<atom:link href="https://inero-software.com/category/blog/tutorials/feed/" rel="self" type="application/rss+xml" />
	<link>https://inero-software.com/category/blog/tutorials/</link>
	<description>We unleash innovations using cutting-edge technologies, modern design and AI</description>
	<lastBuildDate>Mon, 06 Mar 2023 08:02:43 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://inero-software.com/wp-content/uploads/2018/11/inero-logo-favicon.png</url>
	<title>Tutorials - Inero Software - Software Consulting</title>
	<link>https://inero-software.com/category/blog/tutorials/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">153509928</site>	<item>
		<title>Spring Boot 3.0 migration overview</title>
		<link>https://inero-software.com/spring-boot-3-0-migration-overview/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Mon, 06 Mar 2023 08:01:19 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Jakarta]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[JDK]]></category>
		<category><![CDATA[migration]]></category>
		<category><![CDATA[Spring]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=5008</guid>

					<description><![CDATA[<p>SPRING 3.0 MIGRATION OVERVIEW Spring Boot 3.0 has just been released, packed with exciting new features such as advanced observability, better support for native compilation with Graal, and the ability to utilize the latest Java language features. However, for many individuals, upgrading to this latest version may appear overwhelming. The&#8230;</p>
<p>Artykuł <a href="https://inero-software.com/spring-boot-3-0-migration-overview/">Spring Boot 3.0 migration overview</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3></h3>
<h2><img decoding="async" data-attachment-id="1596" data-permalink="https://inero-software.com/?attachment_id=1596" data-orig-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-software-glify-10" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-1596" src="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" alt="Separating icon" width="90" height="90" srcset="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10-80x80.png 80w" sizes="(max-width: 90px) 100vw, 90px" /></h2>
<h3 style="text-align: center;"><span style="color: #800080;">SPRING 3.0 MIGRATION OVERVIEW</span></h3>
<p><img decoding="async" data-attachment-id="2768" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-08/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Glyph v8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" tabindex="0" role="button" class=" wp-image-2768 alignleft" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" alt="Paragrapgh icon" width="81" height="81" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-50x50.png 50w" sizes="(max-width: 81px) 100vw, 81px" />Spring Boot 3.0 has just been released, packed with exciting new features such as advanced observability, better support for native compilation with Graal, and the ability to utilize the latest Java language features. However, for many individuals, upgrading to this latest version may appear overwhelming. The reason being, it requires the updating of many other aspects, such as the Java versions and a transition to Jakarta EE 9. Additionally, given the probability of your organization running several different dependency versions, the migration process can become even more complicated.</p>
<p>It is common to adopt an approach that revolves around the ideology of &#8220;if it&#8217;s not broken, why fix it?&#8221; However, it is important to note that the support for Spring Boot 2.x is scheduled to end by the end of 2023. Additionally, upgrading to the latest version of Spring Boot will provide you with access to a range of new features available across different tools. For instance, upgrading to Java 17, a prerequisite for Spring Boot 3.0, will not only grant you access to a variety of new Java language features (such as pattern matching, records, switch expressions, etc.), but it will also improve the performance of the virtual machine and garbage collector.</p>
<h2><img decoding="async" data-attachment-id="1596" data-permalink="https://inero-software.com/?attachment_id=1596" data-orig-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-software-glify-10" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-1596" src="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" alt="Separating icon" width="62" height="62" srcset="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10-80x80.png 80w" sizes="(max-width: 62px) 100vw, 62px" /></h2>
<h3 style="text-align: center;"><span style="color: #800080;">MAIN STEPS</span></h3>
<p>Migrating to Spring Boot 3.0 necessitates a series of associated migrations and dependency updates that must be carried out before upgrading to this latest version of Spring Boot. These include:<br />
• Updating your organization&#8217;s applications, infrastructure, and CI/CD pipeline to use Java 17. The upside to this step is that it can be done before updating any of your Spring Boot applications.<br />
• Any pre-existing Spring applications that utilize Java EE will require an update to Jakarta EE 9. While this may seem like a simple task of moving all imports from the javax namespace to the jakarta namespace, it also requires the migration of any third-party libraries to versions that are compatible with Jakarta EE 9.</p>
<pre>import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
-&gt;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;</pre>
<p>There are instances when we may not need to refactor package names when upgrading our software, as some dependencies such as <code>javax.sql.DataSource</code> already belong to JDK 17, not Jakarta EE. In these cases, it is not necessary to make any changes to the package name, as it is already consistent with the latest version of our app. It is important to note, however, that it is essential to thoroughly review and test all dependencies to ensure that they are compatible with the new version of the code.</p>
<p>• Lastly, depending on which version of Spring Boot your applications are being migrated from, there may be a need to make several required changes to both the application&#8217;s code and configuration when moving to Spring Boot 3.0.<br />
It is crucial to take note of these steps, as they are all essential requirements that must be fulfilled before upgrading. Sometimes we need to just upgrade dependency version, sometimes we have to migrate to a new package. For example:</p>
<pre>&lt;dependency&gt;
&lt;groupId&gt;org.springdoc&lt;/groupId&gt;
&lt;artifactId&gt;springdoc-openapi-ui&lt;/artifactId&gt;
&lt;version&gt;1.6.11&lt;/version&gt;
&lt;/dependency&gt;
-&gt;
&lt;dependency&gt;
&lt;groupId&gt;org.springdoc&lt;/groupId&gt;
&lt;artifactId&gt;springdoc-openapi-starter-webmvc-ui&lt;/artifactId&gt;
&lt;version&gt;2.0.0&lt;/version&gt;
&lt;/dependency&gt;</pre>
<h2><img loading="lazy" decoding="async" data-attachment-id="1596" data-permalink="https://inero-software.com/?attachment_id=1596" data-orig-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-software-glify-10" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-1596" src="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" alt="Separating icon" width="65" height="65" srcset="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10-80x80.png 80w" sizes="(max-width: 65px) 100vw, 65px" /></h2>
<h3 style="text-align: center;"><span style="color: #800080;">POST MIGRATION ISSUES &#8211; COMMON EXAMPLES</span></h3>
<h4 style="text-align: center;">#1</h4>
<p>Now let&#8217;s look at a situation where we want to update a library used by other applications as a Maven dependency.</p>
<pre>Parameter 0 of constructor in com.some.package.a.Class required a bean of type 'com.some.package.b.SomeExternalClass' that could not be found.</pre>
<p>There is a good chance that exporting configuration files is the cause. Before 3.0, Spring Boot checked for the presence of a <code>META-INF/spring.factories</code> file within your published jar. The file should list your configuration classes under the <code>EnableAutoConfiguration</code> key. Now, instead of providing configuration in META-INF/spring.factories, you would do so in <code>META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports</code>.</p>
<pre>org.springframework.boot.autoconfigure.EnableAutoConfiguration=pl.inero.commons.email.EmailServiceConfiguration
-&gt;
pl.inero.commons.email.EmailServiceConfiguration</pre>
<p>We&#8217;llonfiguration properties for Redis have moved from spring.redis. to spring.data.redis. as redis auto-configuration requires Spring Data to be present on the classpath. Also configuration Properties for Cassandra have moved from spring.data.cassandra. to spring.cassandra..</p>
<p>Now let&#8217;s take some Spring Security related issue.</p>
<h4 style="text-align: center;">#2</h4>
<pre>Invalid CSRF token found for http://localhost:8080/api/test
Responding with 403 status code</pre>
<p>When using Spring Security, it&#8217;s important to be aware of changes between different versions of the framework. For example, in Spring Security version 5, the CsrfToken is loaded by default on each request, which means that even unnecessary requests must have the HttpSession read in a typical setup. However, the default behavior of Spring Security 6 is to postpone the lookup of the CsrfToken until it is actually required.</p>
<p>In our particular application, the CsrfToken is required for every request, so we need to make sure that we specifically opt into the 5.8 defaults to ensure that the CsrfToken is loaded on every request, as it was in version 5. This is a necessary step to ensure that our application runs as intended and that we do not encounter any issues related to the CsrfToken during runtime.</p>
<pre>@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
/ ... /
.csrf(csrf -&gt; csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
/ ... /
}
-&gt;
@Bean
DefaultSecurityFilterChain springSecurity(HttpSecurity http) throws Exception {
CsrfTokenRequestAttributeHandler requestHandler = new CsrfTokenRequestAttributeHandler();
requestHandler.setCsrfRequestAttributeName(null);
return http
/ ... /
.csrf((csrf) -&gt; csrf
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.csrfTokenRequestHandler(requestHandler)
/ ... /
}</pre>
<h4 style="text-align: center;">#3</h4>
<pre>Cannot resolve method 'antMatchers()' (...)</pre>
<p>Methods like antMatchers() (as well as mvcMathcers() and regexMatchers()) have been deprecated and removed with Spring Security 6.0 (have a look at this link if you wonder why: <a href="https://github.com/spring-projects/spring-framework/issues/28552">Deprecate trailing slash match</a>). Overloaded method requestMatchers() was provided as a uniform mean for securing requests. It facilitates all the functionality of the configuration methods that have been removed from the API.</p>
<p>Also, method authorizeRequests() has been deprecated and shouldn&#8217;t be used anymore. A recommended replacement &#8211; authorizeHttpRequests() (you can find more information regarding these changes <a href="https://stackoverflow.com/questions/28907030/spring-security-authorize-request-for-certain-url-http-method-using-httpsecu/74633151#74633151">here</a>). Here we have sample code and how it could have been changed:</p>
<pre>http.requestMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher(API_KEY_URI_MATCHER)))
.httpBasic().and()
.authorizeRequests()
.antMatchers("/ping").permitAll()
.anyRequest().authenticated();

-&gt;

http.securityMatcher(new NegatedRequestMatcher(new AntPathRequestMatcher(API_KEY_URI_MATCHER)))
.httpBasic().and()
.authorizeHttpRequests()
.requestMatchers("/ping").permitAll()
.anyRequest().authenticated();</pre>
<p>&nbsp;</p>
<h2><img loading="lazy" decoding="async" data-attachment-id="1596" data-permalink="https://inero-software.com/?attachment_id=1596" data-orig-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-software-glify-10" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-1596" src="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png" alt="Separating icon" width="68" height="68" srcset="https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2018/11/inero-glify-10-80x80.png 80w" sizes="(max-width: 68px) 100vw, 68px" /></h2>
<h3 style="text-align: center;"><span style="color: #800080;">ON CONFIGURATION PROPERTIES</span></h3>
<p>When upgrading to Spring Boot 3.0, it is essential to update the configuration properties in the <code>application.properties</code> or <code>application.yml</code> files to account for any changes or removals of properties. Spring Boot provides a convenient tool called <code>spring-boot-properties-migrator</code> to help with this migration. By adding this module as a dependency to our project, it will migrate the properties temporarily at runtime and analyze the application&#8217;s environment to print diagnostics at startup.</p>
<p>To add the <code>spring-boot-properties-migrator</code> module to our project, we need to add the following dependency to the <code>pom.xml</code> file.</p>
<pre>&lt;dependency&gt;
&lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
&lt;artifactId&gt;spring-boot-properties-migrator&lt;/artifactId&gt;
&lt;version&gt;3.0.0&lt;/version&gt;
&lt;scope&gt;runtime&lt;/scope&gt;
&lt;/dependency&gt;</pre>
<p>This will ensure that our properties are migrated correctly and that we can benefit from any diagnostics provided by the module during startup.</p>
<p>As always, more tips on migration can be found in the Spring documentation. <a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide">Check it out now</a>.</p>
<p>In <a href="http://inero-software.com">Inero Software</a> we build digital products for <a href="https://inero-software.com/services/">digital logistics of tomorrow.</a> We connect active aproach to analysis of business needs and combine with cutting edge technologies and<a href="https://inero-software.com/machine-learning-professionals/"> AI/ML</a>. In the <a href="https://inero-software.com/category/blog/company">blog post section</a> you will find other articles about IT systems and more!</p>
<p>Artykuł <a href="https://inero-software.com/spring-boot-3-0-migration-overview/">Spring Boot 3.0 migration overview</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">5008</post-id>	</item>
		<item>
		<title>Building a custom voice command recognition system</title>
		<link>https://inero-software.com/building-a-voice-command-recognition-system/</link>
		
		<dc:creator><![CDATA[Andrzej Chybicki]]></dc:creator>
		<pubDate>Mon, 28 Mar 2022 14:12:11 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[ASR models]]></category>
		<category><![CDATA[deepspeech]]></category>
		<category><![CDATA[language model]]></category>
		<category><![CDATA[neural networks]]></category>
		<category><![CDATA[voice command recognition]]></category>
		<category><![CDATA[voice recognition system]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=4795</guid>

					<description><![CDATA[<p>The voice recognition system plays the role of an assistant that will find appropriate information for us, facilitate online shopping or enable the operation of various devices without the use of external buttons or adjustments.</p>
<p>Artykuł <a href="https://inero-software.com/building-a-voice-command-recognition-system/">Building a custom voice command recognition system</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>&nbsp;</p>
<div class="row">
<p><div class="col-sm-1"></div></p>
<p><div class="col-sm-10">
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class=" wp-image-2770 aligncenter" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" alt="" width="75" height="75" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w" sizes="(max-width: 75px) 100vw, 75px" /></p>
<p>&nbsp;</p>
<h2><span style="color: #800080;">How to build your own custom voice command recognition system?</span></h2>
<p>&nbsp;</p>
<p><span data-contrast="auto"><span class="TextRun SCXW189727610 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW189727610 BCX0"><span class="TextRun SCXW21457896 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW21457896 BCX0"><img loading="lazy" decoding="async" data-attachment-id="2768" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-08/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Glyph v8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" tabindex="0" role="button" class=" wp-image-2768 alignleft" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" alt="" width="71" height="71" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-50x50.png 50w" sizes="(max-width: 71px) 100vw, 71px" /></span></span></span></span></span>The concept of voice assistant was created to improve human life. It plays the role of an tool which will find appropriate information for us, facilitate online shopping or manage the operation of various devices without any pressing or regulating. However, creating such a system from scratch can be a difficult challenge. Especially if we want to build it in language other than english.</p>
<p>There are general models of neural networks that are dedicated to spoken language recognition, i.e. transcription from audio to text. Everything depends on how much data we have. Nowadays, there are many recordings of the English language that are decently prepared. However, data alone is not enough. Transcripts must be attached to them. Unfortunately, in Polish we do not have a many voice samples with transcripts. So today we are not able to teach models as well as it is done in English.</p>
<p>So far, we cannot train assistants using open source models with satisfactory effectiveness, but we can check what we are able to build from generally available data. The goal of our work is to create a speech recognition system that actually works.</p>
<p>&nbsp;</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class=" wp-image-2770 aligncenter" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" alt="" width="75" height="75" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w" sizes="(max-width: 75px) 100vw, 75px" /></p>
<p>&nbsp;</p>
<h2><span style="color: #800080;">Preparation and standardization of data for voice command recognition system</span></h2>
<p>&nbsp;</p>
<p><span data-contrast="auto"><span class="TextRun SCXW189727610 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW189727610 BCX0"><span class="TextRun SCXW21457896 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW21457896 BCX0"><img loading="lazy" decoding="async" data-attachment-id="2768" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-08/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Glyph v8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" tabindex="0" role="button" class=" wp-image-2768 alignleft" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" alt="" width="71" height="71" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-50x50.png 50w" sizes="(max-width: 71px) 100vw, 71px" /></span></span></span></span></span>First, we need to ensure the minimum and maximum length of the recording. They must be within a certain time frame. Long recording may be a problem when training the model, while short recording may not carry any relevant information. We also need to ensure that the signal is sampled at the same rate. This is an important point when we are teaching sound based models.</p>
<p>A pure tone sound wave propagating in space is sinusoidal. Changing the frequency of such a sound means a change in the period of the sinusoid, so the distances between its crests change. However, the sound in the computer also has to be presented in some way. The sine wave is continuous and the computer stores individual values. The sampling rate tells us how many times per second the value of the sound wave was recorded. It is important that each sound that enters our model has the same sampling rate.</p>
<p>Due to incorrect sampling the reconstructed sound can be distorted or completely inaudible. Therefore, it is necessary to remember about the appropriate selection of the sampling frequency to minimize the size of the saved data with the simultaneous lack of information loss. Sampling too rarely can cause aliasing, i.e. the overlap between higher frequencies and lower frequencies. For example, a sound that is a mechanical sinusoidal wave with a frequency of 3 Hz may be misinterpreted as a lower frequency signal. This situation is presented in the figure below, in which a sinusoidal signal with a frequency of 5 Hz was interpreted as a signal with a frequency of 1 Hz due to a too low sampling frequency.</p>
<p><img loading="lazy" decoding="async" data-attachment-id="4796" data-permalink="https://inero-software.com/building-a-voice-command-recognition-system/picture1-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2022/03/Picture1.jpg" data-orig-size="454,340" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Picture1" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2022/03/Picture1-300x225.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2022/03/Picture1.jpg" tabindex="0" role="button" class="aligncenter wp-image-4796 size-full" src="https://inero-software.com/wp-content/uploads/2022/03/Picture1.jpg" alt="interpretation of sinusoidal signal" width="454" height="340" srcset="https://inero-software.com/wp-content/uploads/2022/03/Picture1.jpg 454w, https://inero-software.com/wp-content/uploads/2022/03/Picture1-300x225.jpg 300w, https://inero-software.com/wp-content/uploads/2022/03/Picture1-401x300.jpg 401w" sizes="(max-width: 454px) 100vw, 454px" /></p>
<p style="text-align: center;"><em>Source: </em><a href="https://pbc.gda.pl/dlibra/publication/109835/edition/98484/content"><em>Reprezentacje danych dźwiękowych w kontekście metod uczenia maszynowego</em></a><em>, Tymoteusz Cejrowski</em></p>
<p>This is prevented by sampling the signal at a frequency of at least twice the highest frequency in the signal. This is called the Nyquist frequency. For example, recording on CDs are saved at a sampling rate of 44100 Hz. On the other hand, the maximum correctly reconstructed frequency will be 22050 Hz, which corresponds to the upper range of sounds audible by humans.</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class=" wp-image-2770 aligncenter" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" alt="" width="75" height="75" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w" sizes="(max-width: 75px) 100vw, 75px" /></p>
<p>&nbsp;</p>
<h2><span lang="EN-US" style="color: #800080;">Description and teaching of the deepspeech model</span></h2>
<p>&nbsp;</p>
<p><span data-contrast="auto"><span class="TextRun SCXW189727610 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW189727610 BCX0"><span class="TextRun SCXW21457896 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW21457896 BCX0"><img loading="lazy" decoding="async" data-attachment-id="2768" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-08/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Glyph v8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" tabindex="0" role="button" class=" wp-image-2768 alignleft" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" alt="" width="48" height="48" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-50x50.png 50w" sizes="(max-width: 48px) 100vw, 48px" /></span></span></span></span></span>Neural networks are somewhat like the nervous system. The basic units in such networks are neurons, which are arranged in layers. It is a simplified model of information processing by the human mind.</p>
<p>Typically, a neural network consists of three parts. The first is the input layer which has units representing the input variables. The next part is the hidden layers that contain the unobserved entities and are the hidden state of the neural network. It is on these layers that the efficiency of the model largely depends. The last part, of course, is the output layer, which has units representing the targets. All interconnected units are specific connections of different weights. The input data is on the first later, it goes through the next layer, and finally we get the result from the output layer.</p>
<p>The neural network can learn by comparing records. It generates predictions for specific data (audio recordings) and introduces weights adjustments if the generate an incorrect prediction (wrong transcription). The whole process is repeated many times until the accuracy is satisfactory. All weights are random at first and outgoing responses don’t make such sense, while the network improves its predictions over time. This is because the network adapts to the data as it learns.</p>
<p>One of the simplest models of Neural Networks is the <strong>Multilayer Perceptron</strong>. It consists of many neural layers. The neurons of the previous layer form a specific vector that is fed to the entry of neurons into the next layer. A single neuron in the next layer has the number of inputs equal to the number of neurons in the previous layer +1. However, within one layer, the neurons do not have any connections with each other. This type of model is also known as the “Feed-Forward” model and is one of the fundamental architectures of neural networks.</p>
<p><img loading="lazy" decoding="async" data-attachment-id="4797" data-permalink="https://inero-software.com/building-a-voice-command-recognition-system/picture2-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2022/03/Picture2-1.png" data-orig-size="361,461" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Picture2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2022/03/Picture2-1-235x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2022/03/Picture2-1.png" tabindex="0" role="button" class="aligncenter wp-image-4797 size-full" src="https://inero-software.com/wp-content/uploads/2022/03/Picture2-1.png" alt="feed-forward model" width="361" height="461" srcset="https://inero-software.com/wp-content/uploads/2022/03/Picture2-1.png 361w, https://inero-software.com/wp-content/uploads/2022/03/Picture2-1-235x300.png 235w" sizes="(max-width: 361px) 100vw, 361px" /></p>
<p style="text-align: center;"><em>Figure representing the “Feed-Forward” model.</em></p>
<p><strong>Recursive networks</strong> differ from Feed-Forward networks in many respects. One of the main differences is how the input data is propagated to the output of the network. In the simplest model, the network output is nothing but a combination of weights and the model input (single record). For recursive networks, the model output also depends on the previous output. The result of the model operation for the X record is taken into account when calculating the output for the next Y record.</p>
<p>A <strong>convolutional neural network</strong> is the type of network most commonly used for visual image analysis due to its input processing nature. Like a human, this network does not analyse the image pixel by pixel, but captures the patterns present in the input thanks to the use of the so-called Kernels or filters. Each layer in the neural network learns image characteristics such as contours and light saturation. Submitting this information improves the efficiency of the model.</p>
<p>However, it is worth looking at open source systems that enable the creation of voice command recognition. One of them is <a href="https://kaldi-asr.org"><strong>Kaldi</strong></a>, which was written in C++. It was created in 2009 and its main features are that the system is extensible. The community itself provides many other modules that you can use for your own tasks. Kaldi also supports deep neural networks. Although it is written mainly in C++, it has Bash and Python scripts.</p>
<p>For the construction of the voice command recognition system, we focused on the <a href="https://github.com/SeanNaren/deepspeech.pytorch"><strong>deepspeech 2</strong></a> model. It uses deep learning and it consists of 3 convolutional layers, 8 recursive layers and one Fully-Connected (described as Feed-Forward). Deepspeech 2 can be successfully trained in any language, but you have to remember that models are most often issued only with code, so you have to learn them yourself. For popular languages such as English and Mandarin, there are pre-trained ready-to-use models. For our assignment, we chose deepspeech 2 with a <a href="https://github.com/SeanNaren/deepspeech.pytorch">PyTorch</a> implementation because it is lightweight, relatively few parameters (weights to learn), and is actively maintained. In this model, in addition to preparing the appropriate sampling frequencies about which we wrote above, we also had to prepare the data for the deepspeech model itself. This was related to the provision of an appropriate directory structure.</p>
<p>&nbsp;</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class=" wp-image-2770 aligncenter" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" alt="" width="75" height="75" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w" sizes="(max-width: 75px) 100vw, 75px" /></p>
<p>&nbsp;</p>
<h2><span lang="EN-US" style="color: #800080;">Reasoning with the use of ASR models and an additional language model</span></h2>
<p>&nbsp;</p>
<p><span data-contrast="auto"><span class="TextRun SCXW189727610 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW189727610 BCX0"><span class="TextRun SCXW21457896 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW21457896 BCX0"><img loading="lazy" decoding="async" data-attachment-id="2768" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-08/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Glyph v8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" tabindex="0" role="button" class=" wp-image-2768 alignleft" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" alt="" width="101" height="101" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-50x50.png 50w" sizes="(max-width: 101px) 100vw, 101px" /></span></span></span></span></span>Using deepspeech we are able to apply an additional language model (n-gram model). It is based on statistics and helps predict the next element in the sequence. It must be remembered that the application of such a model requires the collection of a large amount of statistical data. N-grams help machines understand a word in a specific context. This allows them to understand its purpose better. So if you want to build an effective voice command recognition system, it is worth considering.</p>
<p>If we want to create such a model, we start by counting the occurrences of a sequence of a fixed length in the existing linguistic resources. Therefore, whole texts are analysed and single occurrences (1 gram) twos (2 grams) and triples (3 grams) are counted. We can also obtain a 4-gram model, but here huge sets of data are needed, which makes it challenging for the Polish language to implement.</p>
<p>Then you convert the number of occurrences into probability by normalizing. In this way, we obtain the prediction of the next element based on the sequences so far. The more text we analyse, the higher the quality of the model will be. This data is used in natural language processing (NLP) applications. However, there are methods that allow n-gram models to be improved by smoothing the collected statistics. This model is primarily characterized by scalability. We can choose a schema without a lot of data, but then it will be less predictive. The n-gram model for the Polish language can be found <a href="https://zasobynauki.pl/zasoby/model-jezykowy-dla-jezyka-polskiego,55644/">here</a>.</p>
<p>The use of the n-gram model at the inference stage allows to correct the output of the neural network (transcription of the deepspeech 2 model) in accordance with the rules contained in the n-gram model.</p>
<p>&nbsp;</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class=" wp-image-2770 aligncenter" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" alt="" width="75" height="75" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w" sizes="(max-width: 75px) 100vw, 75px" /></p>
<p>&nbsp;</p>
<h2><span lang="EN-US" style="color: #800080;">Operation on a limited set of commands</span></h2>
<p>&nbsp;</p>
<p><span data-contrast="auto"><span class="TextRun SCXW189727610 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW189727610 BCX0"><span class="TextRun SCXW21457896 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW21457896 BCX0"><img loading="lazy" decoding="async" data-attachment-id="2768" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-08/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Glyph v8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" tabindex="0" role="button" class=" wp-image-2768 alignleft" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" alt="" width="101" height="101" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-50x50.png 50w" sizes="(max-width: 101px) 100vw, 101px" /></span></span></span></span></span>Unfortunately, the models built cannot be learned well enough due to the small amount of data in a language we work in &#8211; Polish. In our case, we can operate in a limited set of commands. This means that a specific number of voice commands will be recognized. Our task was to match the appropriate command from the set with what the model provides us. It is important here to define the highest similarity between the command and what the model returned to us.</p>
<p>For this task, we used a metric called <strong>Levenshtein distance</strong>, which indicates the similarity between the transcript and a given command. It consists of counting items or letters that do not match. For example, the Levenshtein distance between the terms:</p>
<ul>
<li>Gravity</li>
<li>Gravity</li>
</ul>
<p>Is zero. These words are identical, so no action is required here.</p>
<p>On the other hand, the Levenshtein distance between the words:</p>
<ul>
<li>Long</li>
<li>Pork</li>
</ul>
<p>Is 3, because it takes at least 3 actions: replace <strong>L</strong> with <strong>P</strong>, replace <strong>n </strong>with <strong>r</strong>, and replace<strong> g</strong> with <strong>k</strong>.</p>
<p>Where there are fewest substitutions, we have the greatest probability that the commands are the same.</p>
<p>&nbsp;</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class=" wp-image-2770 aligncenter" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" alt="" width="75" height="75" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w" sizes="(max-width: 75px) 100vw, 75px" /></p>
<p>&nbsp;</p>
<h2><span style="color: #800080;">Summary</span></h2>
<p>&nbsp;</p>
<p><span data-contrast="auto"><span class="TextRun SCXW189727610 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW189727610 BCX0"><span class="TextRun SCXW21457896 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW21457896 BCX0"><img loading="lazy" decoding="async" data-attachment-id="2768" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-08/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Glyph v8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" tabindex="0" role="button" class=" wp-image-2768 alignleft" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png" alt="" width="101" height="101" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08.png 208w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-08-50x50.png 50w" sizes="(max-width: 101px) 100vw, 101px" /></span></span></span></span></span>The purpose of voice recognition systems is to ensure ease of communication between the device and the human being. Speech recognition technology is already a part of our daily lives. For now, it is limited to relatively simple commands. Building such a system based on data in the Polish language is a difficult task due to the small amount of data. Taking into account the current trends in the use of smart devices and technical possibilities, it is worth exploring the potential of these systems.</p>
<p><a href="https://inero-software.com/contact-us/"><strong><span style="color: #800080;">Inero Software</span></strong></a> provides knowledge and expertise on how to successfully use cutting edge technologies and data to shape corporate digital products of the future.</p>
<p><span data-contrast="auto">In the <a href="https://inero-software.com/category/blog/company/"><strong><span style="color: #800080;">blog post</span></strong></a> section you will find other articles about IT systems and more!</span></p>
<p><strong>Consulted by: Tymoteusz Cejrowski, Software Developer.</strong></p>
<p></p></div><br />
</p></div>
<p>Artykuł <a href="https://inero-software.com/building-a-voice-command-recognition-system/">Building a custom voice command recognition system</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">4795</post-id>	</item>
		<item>
		<title>Android Kiosk Mode &#8211; how to turn an Android device into a single-use device</title>
		<link>https://inero-software.com/android-kiosk-mode-how-to-turn-an-android-device-into-a-single-use-device/</link>
		
		<dc:creator><![CDATA[Andrzej Chybicki]]></dc:creator>
		<pubDate>Thu, 18 Mar 2021 11:36:35 +0000</pubDate>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[corporate]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[single use device]]></category>
		<guid isPermaLink="false">https://sandbox-www.devel.inero.com.pl/?p=3353</guid>

					<description><![CDATA[<p>In Inero Software – software development agency, we are experts of digital transformation and smart automation. We provide knowledge and expertise on how to successfully use cutting edge technologies and data to shape corporate digital products of the future. Find out more visiting our website or contacting us directly on&#8230;</p>
<p>Artykuł <a href="https://inero-software.com/android-kiosk-mode-how-to-turn-an-android-device-into-a-single-use-device/">Android Kiosk Mode &#8211; how to turn an Android device into a single-use device</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="row"><div class="col-sm-1"></div><div class="col-sm-10">
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<p><span style="font-weight: 400;">I believe that the Android OS needs no introduction. It is currently the most popular smartphone operating system. However, the days when Android was only used in consumer electronics are behind us. Today we can meet Android devices at every step. It is increasingly used in industries such as security, automation, logistics, sales, hospitality, etc. </span><span style="font-weight: 400;">Due to its ease of use, flexibility, level of customization and lower cost, Android devices are the choice of many enterprises and organizations. However, for many companies Android systems are not considered safe enough for use in the workplace or like all mobile devices are too distracting. </span><span style="font-weight: 400;">One of the best solutions to the above problems is the Kiosk Mode tool, which allows us to convert your Android device into a dedicated app, while providing additional security and reducing additional distractions. Enjoy your reading!</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h2><span style="color: #800080;"><b>COSU &#8211; corporate-owned single use device</b></span></h2>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />Dedicated devices (formerly called corporate-owned single-use, or COSU) are fully managed devices that serve a specific purpose. Thanks to this, it is possible to maximize the use of the device, while limiting use of personal and non-supervised functions like telephony, messaging etc. We deal with many such devices every day. These include vending machines, automatic ticket printers, parking meters or interactive information boards in shopping malls. COSU allows IT administrators to remotely control all these devices and can lock the device for a specific application. This prevents users from using other applications or performing other activities on these devices.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h2><span style="color: #800080;"><b>Kiosk Mode</b></span></h2>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<p><span style="font-weight: 400;">Kiosk mode allows to turn Android devices into single-use devices by running only one application or a specific set of applications. Starting with Android 5.0 Lollipop, the system offers two ways to lock the device for a specific purpose:</span></p>
<p>&nbsp;</p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">App pinning &#8211; Using the app pinning feature, users can temporarily pin any installed app on the screen. The navigation buttons (Home and Recent apps) are visible but inactive. The user can exit this mode by holding down the Home and Recent apps buttons simultaneously.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Lock task mode &#8211; This is an even more effective way to switch your Android device into a single-purpose kiosk. Only applications whitelisted by the Device Policy Controller (DPC) may be blocked. The navigation buttons (Home and Recent apps) are hidden. Exiting this mode is done by calling the stopLockTask() method. This mode is available to only device owner devices.</span></li>
</ul>
<p><span style="font-weight: 400;">Running the application in Kiosk Mode gives us a number of benefits:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">device acts as a single application platform,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">hidden navigation buttons (Lock task mode),</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">inactive status bar,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">automatic app startup with system startup,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">disabled notifications,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">blocked incoming calls,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">inactive transition to settings,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">working in full screen mode.</span></li>
</ul>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h2><span style="color: #800080;"><b>How to enable Android Kiosk Mode?</b></span></h2>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">The first step is to implement the class inheriting from the DeviceAdminReceiver class:</span></p>
<p>&nbsp;</p>
<pre><span style="font-weight: 400;">class MyDeviceAdminReceiver : DeviceAdminReceiver() {</span>
<span style="font-weight: 400;">    companion object {</span>
<span style="font-weight: 400;">        fun getComponentName(context: Context): ComponentName {</span>
<span style="font-weight: 400;">            return ComponentName(context.applicationContext, MyDeviceAdminReceiver::class.java)</span>
<span style="font-weight: 400;">        }</span>
<span style="font-weight: 400;">    }</span>
<span style="font-weight: 400;">}</span></pre>
<p><span style="font-weight: 400;">DeviceAdminReceiver is a </span><span style="font-weight: 400;">class which provides a convenience for interpreting the raw intent actions that are sent by the system.</span></p>
<p><span style="font-weight: 400;">Then we have to inform the system that our application wants to become the device administrator. We can do this by adding a receiver in the AndroidManifest.xml file:</span></p>
<pre><span style="font-weight: 400;">&lt;application&gt;</span>
<span style="font-weight: 400;">          ...</span>
<span style="font-weight: 400;">      &lt;receiver</span>
<span style="font-weight: 400;">            android:name=".MyDeviceAdminReceiver"</span>
<span style="font-weight: 400;">            android:description="@string/app_desc"</span>
<span style="font-weight: 400;">            android:label="@string/app_name"</span>
<span style="font-weight: 400;">            android:permission="android.permission.BIND_DEVICE_ADMIN"&gt;</span>
<span style="font-weight: 400;">            &lt;meta-data</span>
<span style="font-weight: 400;">                android:name="android.app.device_admin" /&gt;</span>
<span style="font-weight: 400;">            &lt;intent-filter&gt;</span>
<span style="font-weight: 400;">                &lt;action android:name="android.app.action.DEVICE_ADMIN_ENABLED" /&gt;</span>
<span style="font-weight: 400;">            &lt;/intent-filter&gt;</span>
<span style="font-weight: 400;">        &lt;/receiver&gt;</span>
<span style="font-weight: 400;">    &lt;/application&gt;</span></pre>
<p><span style="font-weight: 400;">At this point, we can proceed to the installation of the application. Note that, in order to grant administration rights to the app, you must remove all existing users.  The easiest way is to apply a factory reset your device. It is important not to add a Google account to the device during the first start-up after the reset. List of steps for correct configuration is as follows:</span></p>
<ol>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">factory reset on your mobile device,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">skip the steps related to adding a Google account,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">enable the developer mode and USB debugging on the mobile device,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">install adb (Android Device Bridge) on your computer &#8211; it is automatically installed with the Android Studio environment,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">install the application on a mobile device using Android Studio or by entering the following commands in the console: </span><span style="font-weight: 400;"> </span>
<ol>
<li style="font-weight: 400;" aria-level="1">
<pre>adb install path / to / kiosk / application.apk</pre>
</li>
</ol>
</li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">grant the application device administrator privileges:</span>
<ol>
<li style="font-weight: 400;" aria-level="2">
<pre><span style="font-weight: 400;">adb shell dpm set-device-owner pl.inero.deliverM8 / .MyDeviceAdminReceiver</span></pre>
</li>
</ol>
</li>
</ol>
<p><span style="font-weight: 400;">Use the following code snippet to verify that the granting process was successful:</span></p>
<pre><span style="font-weight: 400;">override fun onCreate(savedInstanceState: Bundle?) {</span>
<span style="font-weight: 400;">        super.onCreate(savedInstanceState)</span>
<span style="font-weight: 400;">        mDevicePolicyManager = getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager</span>
<span style="font-weight: 400;">        val isAdmin = mDevicePolicyManager.isDeviceOwnerApp(packageName)</span>
<span style="font-weight: 400;">        if (isAdmin) {</span>
<span style="font-weight: 400;">            println("You are an admin")</span>
<span style="font-weight: 400;">        } else {</span>
<span style="font-weight: 400;">            println("You are not an admin")</span>
<span style="font-weight: 400;">        }</span>
<span style="font-weight: 400;">    }</span></pre>
<p><span style="font-weight: 400;">Depending on the needs, we can enable the user to disable the Kiosk mode via the interface (e.g. by confirming with a password) or completely block the exit from the application. With the help of the code snippets below, I will try to explain how you can control the device settings to get the solution that best suits your needs.</span></p>
<p><span style="font-weight: 400;">One of the parameters we can control is whether we keep the device on while the device is plugged in. “0” means  to never stay on while plugged in.</span></p>
<pre><span style="font-weight: 400;">private fun enableStayOnWhilePluggedIn(active: Boolean) = if (active) {</span>
<span style="font-weight: 400;">        mDevicePolicyManager.setGlobalSetting(mAdminComponentName,</span>
<span style="font-weight: 400;">                Settings.Global.STAY_ON_WHILE_PLUGGED_IN,</span>
<span style="font-weight: 400;">                (BatteryManager.BATTERY_PLUGGED_AC</span>
<span style="font-weight: 400;">                        or BatteryManager.BATTERY_PLUGGED_USB</span>
<span style="font-weight: 400;">                        or BatteryManager.BATTERY_PLUGGED_WIRELESS).toString())</span>
<span style="font-weight: 400;">    } else {</span>
<span style="font-weight: 400;">        mDevicePolicyManager.setGlobalSetting(mAdminComponentName, Settings.Global.STAY_ON_WHILE_PLUGGED_IN, "0")</span>
<span style="font-weight: 400;">    }</span></pre>
<p><span style="font-weight: 400;">If we want to impose restrictions on the user, we can use the method </span><span style="font-weight: 400;">addUserRestriction(ComponentName admin, String key). The device user must have device administrator rights or a security exception will be thrown. This method can be called on an instance of DevicePolicyManager.</span></p>
<pre><span style="font-weight: 400;">mDevicePolicyManager = getSystemService (Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager</span></pre>
<p><span style="font-weight: 400;">In our case, we have blocked the user from factory reset, adding new users, connecting external media, controlling the device volume and turning off the bar status:</span></p>
<pre><span style="font-weight: 400;">private fun setRestrictions(disallow: Boolean) {</span>
<span style="font-weight: 400;">        setUserRestriction(UserManager.DISALLOW_FACTORY_RESET, disallow)</span>
<span style="font-weight: 400;">        setUserRestriction(UserManager.DISALLOW_ADD_USER, disallow)</span>
<span style="font-weight: 400;">        setUserRestriction(UserManager.DISALLOW_MOUNT_PHYSICAL_MEDIA, disallow)</span>
<span style="font-weight: 400;">        setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, disallow)</span>
<span style="font-weight: 400;">        mDevicePolicyManager.setStatusBarDisabled(mAdminComponentName, disallow)</span>
<span style="font-weight: 400;">    }
</span><span style="font-weight: 400;">private fun setUserRestriction(restriction: String, disallow: Boolean) = if (disallow) {</span>
<span style="font-weight: 400;">        mDevicePolicyManager.addUserRestriction(mAdminComponentName, restriction)</span>
<span style="font-weight: 400;">    } else {</span>
<span style="font-weight: 400;">        mDevicePolicyManager.clearUserRestriction(mAdminComponentName, restriction)</span>
<span style="font-weight: 400;">    }</span></pre>
<p><span style="font-weight: 400;">If we want our application to start with the system startup, then we have to add the appropriate filters:</span></p>
<pre><span style="font-weight: 400;">private fun setAsHomeApp(enable: Boolean) {</span>
<span style="font-weight: 400;">        if (enable) {</span>
<span style="font-weight: 400;">            val intentFilter = IntentFilter(Intent.ACTION_MAIN).apply {</span>
<span style="font-weight: 400;">                addCategory(Intent.CATEGORY_HOME)</span>
<span style="font-weight: 400;">                addCategory(Intent.CATEGORY_DEFAULT)</span>
<span style="font-weight: 400;">            }</span>
<span style="font-weight: 400;">            mDevicePolicyManager.addPersistentPreferredActivity(</span>
<span style="font-weight: 400;">                    mAdminComponentName, intentFilter, ComponentName(packageName, MainActivity::class.java.name))</span>
<span style="font-weight: 400;">        } else {</span>
<span style="font-weight: 400;">            mDevicePolicyManager.clearPackagePersistentPreferredActivities(</span>
<span style="font-weight: 400;">                    mAdminComponentName, packageName)</span>
<span style="font-weight: 400;">        }</span>
<span style="font-weight: 400;">    }</span></pre>
<p><span style="font-weight: 400;">In order to run the application in full screen screen Kiosk Mode , the appropriate flags must be added:</span></p>
<pre><span style="font-weight: 400;">private fun setImmersiveMode(enable: Boolean) {</span>
<span style="font-weight: 400;">        if (enable) {</span>
<span style="font-weight: 400;">            val flags = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE</span>
<span style="font-weight: 400;">                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION</span>
<span style="font-weight: 400;">                    or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN</span>
<span style="font-weight: 400;">                    or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION</span>
<span style="font-weight: 400;">                    or View.SYSTEM_UI_FLAG_FULLSCREEN</span>
<span style="font-weight: 400;">                    or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY</span>
<span style="font-weight: 400;">                    )</span>
<span style="font-weight: 400;">            window.decorView.systemUiVisibility = flags</span>
<span style="font-weight: 400;">            window.decorView.setOnSystemUiVisibilityChangeListener {</span>
<span style="font-weight: 400;">                window.decorView.systemUiVisibility = flags;</span>
<span style="font-weight: 400;">            }</span>
<span style="font-weight: 400;">        } else {</span>
<span style="font-weight: 400;">            val flags = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE</span>
<span style="font-weight: 400;">                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION</span>
<span style="font-weight: 400;">                    or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)</span>
<span style="font-weight: 400;">            window.decorView.systemUiVisibility = flags</span>
<span style="font-weight: 400;">        }</span>
<span style="font-weight: 400;">    }</span></pre>
<p><span style="font-weight: 400;">Finally, we use the startLockTask () and stopLockTask () methods to turn Lock task mode on / off:</span></p>
<pre><span style="font-weight: 400;">private fun setLockTask(start: Boolean, isAdmin: Boolean) {</span>
<span style="font-weight: 400;">        if (isAdmin) {</span>
<span style="font-weight: 400;">            mDevicePolicyManager.setLockTaskPackages(</span>
<span style="font-weight: 400;">                    mAdminComponentName, if (start) arrayOf(packageName) else arrayOf())</span>
<span style="font-weight: 400;">        }</span>
<span style="font-weight: 400;">        if (start) {</span>
<span style="font-weight: 400;">            startLockTask()</span>
<span style="font-weight: 400;">        } else {</span>
<span style="font-weight: 400;">            stopLockTask()</span>
<span style="font-weight: 400;">        }</span>
<span style="font-weight: 400;">    }</span></pre>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<h2><span style="color: #800080;"><b>Results</b></span></h2>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />The above operations allow to change the Android device into a dedicated device, operating in full screen mode and preventing the user from using other functionalities. For the purpose of exemplification of our case, we used a mobile application, developed in our company for <a href="https://inero-software.com/supply-chain-management/">supply chain management</a>. This application is a part of <a href="https://deliverm8.com/">DeliverM8</a> platform, we developed in order to optimize and plan supply chain management tasks for the <a href="https://inero-software.com/deliverm8-last-mile-delivery/">last mile delivery</a>. You can read more about it <a href="https://deliverm8.com/">here</a>. Coming back to the topic of the blogpost, the final  effect is as follows:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="3356" data-permalink="https://inero-software.com/android-kiosk-mode-how-to-turn-an-android-device-into-a-single-use-device/deliverm8-kiosk/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/03/deliverM8-kiosk.png" data-orig-size="441,864" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="deliverM8-kiosk" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/03/deliverM8-kiosk-153x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/03/deliverM8-kiosk.png" tabindex="0" role="button" class="aligncenter wp-image-3356 size-full" src="https://inero-software.com/wp-content/uploads/2021/03/deliverM8-kiosk.png" alt="Android Kiosk Mode visualisation" width="441" height="864" srcset="https://inero-software.com/wp-content/uploads/2021/03/deliverM8-kiosk.png 441w, https://inero-software.com/wp-content/uploads/2021/03/deliverM8-kiosk-153x300.png 153w" sizes="(max-width: 441px) 100vw, 441px" /></p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<h2><span style="color: #800080;"><b>Summary</b></span></h2>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<p><span style="font-weight: 400;">In this blog post we showed how to quickly set up a configuration of a mobile application to get a single purpose device that meets our needs as much as possible. The use of the Kiosk Mode brings many benefits, such as increasing security or limiting access to undesirable functionalities, creating a solution tailored both to the needs of employees (inventory management, field service management, <a href="https://inero-software.com/logistics-solutions/">transport and logistics</a>) and customers (hospitality check-in, self-service kiosks).<br />
</span></p>
<p></p></div><div class="col-sm-1"></div></div>
<h4><b>In <a href="https://inero-software.com">Inero Software</a> – software development agency, we are experts of digital transformation and smart automation. We provide knowledge and expertise on how to successfully use cutting edge technologies and data to shape corporate digital products of the future. Find out more visiting our website or contacting us directly on <a href="mailto:hi@inero-software.com">hi@inero-software.com</a></b></h4>
<p>Artykuł <a href="https://inero-software.com/android-kiosk-mode-how-to-turn-an-android-device-into-a-single-use-device/">Android Kiosk Mode &#8211; how to turn an Android device into a single-use device</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3353</post-id>	</item>
		<item>
		<title>Digital Cloud Document Repositories &#8211; how to identify signatures in scanned PDF documents</title>
		<link>https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/</link>
		
		<dc:creator><![CDATA[Adrian Chojnacki]]></dc:creator>
		<pubDate>Tue, 09 Feb 2021 12:27:55 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[digital repository]]></category>
		<category><![CDATA[document]]></category>
		<category><![CDATA[machinelearning]]></category>
		<category><![CDATA[object detection]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[yolov5]]></category>
		<guid isPermaLink="false">https://sandbox-www.devel.inero.com.pl/?p=3306</guid>

					<description><![CDATA[<p>&#160; Computer vision and object detection are increasingly used in the automation of business processes. Along with the dynamic development of technology, especially artificial intelligence, there are many new innovative business applications for this type of algorithms. In one of our recent posts, we outlined how to build a custom&#8230;</p>
<p>Artykuł <a href="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/">Digital Cloud Document Repositories &#8211; how to identify signatures in scanned PDF documents</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3></h3>
<p>&nbsp;</p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />Computer vision and object detection are increasingly used in the automation of business processes. Along with the dynamic development of technology, especially </span><a href="https://inero-software.com/machine-learning-professionals/"><span style="font-weight: 400;">artificial intelligence</span></a><span style="font-weight: 400;">, there are many new innovative business applications for this type of algorithms. In one of our recent posts, we outlined </span><a href="https://inero-software.com/few-tips-on-how-to-create-custom-class-detection-system-using-r-cnn/?preview=true"><span style="font-weight: 400;">how to build a custom R-CNN based detector</span></a><span style="font-weight: 400;">. In this article, we will walk you through how to do the same with YOLO v5, which has grown in strength in recent years. One of the important aspects over and above other solutions is the speed of inference. As part of this article, we will present the specified use case and all steps of its implementation. Enjoy your reading!</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h2><span style="color: #800080;"><b>Use case</b></span></h2>
<p>&nbsp;</p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />Signatures are still one of the most common methods of document authentication. Especially for enterprise applications, identification of signed and unsigned copies of documents in digital repositories may be time-consuming and a challenging task. However, automation supported by <a href="https://inero-software.com/machine-learning-professionals/">machine learning</a> can make it easier. In this context, we describe the capabilities of YOLO v5 detector, and we will discuss issues of detecting invoice signatures. </span><span style="font-weight: 400;">Let’s start with an example as shown in the figure below. For the purpose of this study, we prepared a fake invoice, fake data of the seller, buyer or the product itself. Let’s investigate now, how we can focus on hand-written signatures (which is fake too :-)).</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="3314" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/invoice/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/invoice.png" data-orig-size="675,675" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="invoice" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/invoice-300x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/invoice.png" tabindex="0" role="button" class="aligncenter wp-image-3314 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/invoice.png" alt="invoice" width="675" height="675" srcset="https://inero-software.com/wp-content/uploads/2021/02/invoice.png 675w, https://inero-software.com/wp-content/uploads/2021/02/invoice-80x80.png 80w, https://inero-software.com/wp-content/uploads/2021/02/invoice-300x300.png 300w, https://inero-software.com/wp-content/uploads/2021/02/invoice-50x50.png 50w, https://inero-software.com/wp-content/uploads/2021/02/invoice-512x512.png 512w" sizes="(max-width: 675px) 100vw, 675px" /></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h4><span style="color: #800080;"><b>Collecting Data</b></span></h4>
<p>&nbsp;</p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />One of the first steps is to collect a set of images to train your model. For our use case, we have prepared a small <strong>10 sample</strong> training set of invoices filled with different data and augmented this collection by a dedicated Python script. To make things easier, we used a</span><span style="font-weight: 400;"> </span><a href="https://roboflow.ai/"><span style="font-weight: 400;">Roboflow</span></a>, which <span style="font-weight: 400;">is a useful tool for data tagging Here you can upload your dataset and make a quick annotation process like on this GIF.</span></p>
<p>&nbsp;</p>
<p><img loading="lazy" decoding="async" data-attachment-id="3310" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/annonated/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/annonated-e1646395509809.gif" data-orig-size="1716,913" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="annonated" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/annonated-e1646395509809-300x160.gif" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/annonated-e1646395509809-1030x548.gif" tabindex="0" role="button" class="aligncenter wp-image-3310 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/annonated-e1646395509809.gif" alt="Upload of the dataset" width="1716" height="913" /></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">Additionally, we can generate more output images with random values ​​of rotation, saturation, exposure, noise, blur and other types of transformations. Moreover, with the help of this tool, we can determine our training, validation and test data split &#8211; the default is 70%, 10%, 10%. This is an important thing to prevent overfitting our model, you can read more about it on </span><a href="http://blog.roboflow.com/train-test-split/"><span style="font-weight: 400;">this blog</span></a><span style="font-weight: 400;">. Thanks to the described tool, we can export our dataset in the </span><i><span style="font-weight: 400;">YOLO v5 Pytorch format</span></i><span style="font-weight: 400;"> and put it in the directory of our project. The figure below shows the selection and target tree, where one of the most important files is the </span><strong>data.yml</strong><span style="font-weight: 400;"> that will be used for training.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="3311" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/export/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/export.png" data-orig-size="555,360" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="export" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/export-300x195.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/export.png" tabindex="0" role="button" class="aligncenter wp-image-3311 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/export.png" alt="Export of the files" width="555" height="360" srcset="https://inero-software.com/wp-content/uploads/2021/02/export.png 555w, https://inero-software.com/wp-content/uploads/2021/02/export-300x195.png 300w, https://inero-software.com/wp-content/uploads/2021/02/export-463x300.png 463w" sizes="(max-width: 555px) 100vw, 555px" /></p>
<p><span style="font-weight: 400;">In our case after the first step of augmentation by a Python script, we generate </span><strong>69</strong> <span style="font-weight: 400;">images. Additionally, we use a noise option in Roboflow, which allows us, in the end, export </span><strong>169</strong> <span style="font-weight: 400;">annotated examples. Our images were ultimately split as shown in the figure below. </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="3316" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/split/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/split.png" data-orig-size="575,106" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="split" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/split-300x55.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/split.png" tabindex="0" role="button" class="aligncenter wp-image-3316 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/split.png" alt="Split of the images" width="575" height="106" srcset="https://inero-software.com/wp-content/uploads/2021/02/split.png 575w, https://inero-software.com/wp-content/uploads/2021/02/split-300x55.png 300w" sizes="(max-width: 575px) 100vw, 575px" /></p>
<p><span style="font-weight: 400;">And here you can see some of the train examples… </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="4933" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/setcomp/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/setcomp.gif" data-orig-size="1206,724" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="setcomp" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/setcomp-300x180.gif" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/setcomp-1030x618.gif" tabindex="0" role="button" class="aligncenter wp-image-4933 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/setcomp.gif" alt="train examples" width="1206" height="724" /></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<p>&nbsp;</p>
<h4><span style="color: #800080;"><b>Model configuration and architecture</b></span></h4>
<p>&nbsp;</p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />The next step in the whole process is to define the configuration and architecture of the YOLO model. We may build our own network structure, although in version 5 we are provided with one of the following models:</span></p>
<p>&nbsp;</p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">YOLOv5s,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">YOLOv5m,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">YOLOv5l,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">YOLOv5x.</span></li>
</ul>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">We may use any of them but we must remember to assign appropriate target file parameter value called </span><strong>nc</strong> <span style="font-weight: 400;">&#8211; </span><i><span style="font-weight: 400;">number of classes</span></i><span style="font-weight: 400;">. In our use case, it’s 1. The models differ from each other with the number of parameters used, speed of frames per second (FPS), accuracy and others&#8230; On the figure below you can see how they cope with the same </span><a href="https://cocodataset.org/#home"><span style="font-weight: 400;">COCO dataset</span></a><span style="font-weight: 400;">. Click on the image below to learn more.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="3319" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/yolo/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/yolo.png" data-orig-size="2400,1200" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="yolo" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/yolo-300x150.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/yolo-1030x515.png" tabindex="0" role="button" class="aligncenter wp-image-3319 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/yolo.png" alt="YOLO graph" width="2400" height="1200" srcset="https://inero-software.com/wp-content/uploads/2021/02/yolo.png 2400w, https://inero-software.com/wp-content/uploads/2021/02/yolo-300x150.png 300w, https://inero-software.com/wp-content/uploads/2021/02/yolo-768x384.png 768w, https://inero-software.com/wp-content/uploads/2021/02/yolo-1030x515.png 1030w, https://inero-software.com/wp-content/uploads/2021/02/yolo-600x300.png 600w" sizes="(max-width: 2400px) 100vw, 2400px" /></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h4><span style="color: #800080;"><b>Training</b></span></h4>
<p>&nbsp;</p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />What’s important, the </span><a href="https://www.ultralytics.com/"><span style="font-weight: 400;">Ultralytics</span></a><span style="font-weight: 400;"> company provides us with YOLO v5 developed in </span><a href="https://pytorch.org/"><span style="font-weight: 400;">PyTorch</span></a><span style="font-weight: 400;">, a framework specialized in machine learning. Thanks to this, we may download their repository from </span><a href="https://github.com/ultralytics/yolov5"><span style="font-weight: 400;">GitHub</span></a><span style="font-weight: 400;"> and train our own detector. Nothing simpler, but what else do we need for everything to work fine? </span></p>
<p><span style="font-weight: 400;">To run each of the scripts we must install the dependencies contained in the </span><i><span style="font-weight: 400;">requirements.txt</span></i><span style="font-weight: 400;">. If we are using </span><strong>pip</strong><span style="font-weight: 400;">, we can use the following command in the terminal. Please remember that you must be in the project directory. </span></p>
<p>&nbsp;</p>
<pre>pip install -r requirements.txt</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">In the installation process, one thing may be a problem. Namely, the </span><i><span style="font-weight: 400;">PyTorch </span></i><span style="font-weight: 400;">library…</span></p>
<p><span style="font-weight: 400;">The different operating system, package in use, programming language etc. may require a specified command. You will find everything you need in this </span><a href="https://pytorch.org/get-started/locally/"><span style="font-weight: 400;">tutorial</span></a><span style="font-weight: 400;">.</span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">Let&#8217;s assume you have passed all the requirements and start our training!</span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">One line of code is enough to run this process, but we need to make sure that we have prepared two important files &#8211; </span><strong>data.yaml</strong> <span style="font-weight: 400;">and for example </span><strong>yolov5l.yaml</strong><span style="font-weight: 400;"><strong>.</strong> The first one you should have from the data collection stage and the second one can be found in the YOLO v5 repository, in the </span><i><span style="font-weight: 400;">Models </span></i><span style="font-weight: 400;">directory. </span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">That&#8217;s it! Let’s run the training by the following command: </span></p>
<p>&nbsp;</p>
<pre>python train.py --data dataset/data.yaml --cfg models/yolov5l.yaml --weights ''</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">The above command is the simplest possible, additionally, you can define the following options or parameters: </span></p>
<p>&nbsp;</p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">img-size,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">batch-size,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">epochs, </span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">name,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">no-save,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">cache…</span></li>
</ul>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">For the purposes of this article, </span><span style="font-weight: 400;">we conducted a relatively short training for images resized to </span><strong>416&#215;416</strong><span style="font-weight: 400;">, batch size </span><strong>32</strong><span style="font-weight: 400;"> and </span><strong>1500</strong><span style="font-weight: 400;"> epochs. When the process is complete, the result will be a weight file named </span><strong>best.pt</strong><span style="font-weight: 400;">.</span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">Perhaps you may stop your learning process if your weights are optimal for you at the moment. We stopped our training after </span><strong>650</strong><span style="font-weight: 400;"> epochs, which took about </span><strong>15</strong> <strong>hours</strong><span style="font-weight: 400;"> in total. Please note that the PC used does not have a dedicated graphics card.</span></p>
<p>&nbsp;</p>
<p><img loading="lazy" decoding="async" data-attachment-id="4935" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/trainingcomp/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/trainingcomp.gif" data-orig-size="1888,212" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="trainingcomp" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/trainingcomp-300x34.gif" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/trainingcomp-1030x116.gif" tabindex="0" role="button" class="aligncenter wp-image-4935 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/trainingcomp.gif" alt="training" width="1888" height="212" /></p>
<h5></h5>
<p>&nbsp;</p>
<h5><strong><span style="color: #800080;">Detailed metrics of our training:</span></strong></h5>
<p>&nbsp;</p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">precision &#8211; </span><strong>0.93507</strong><span style="font-weight: 400;">,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">recall &#8211; </span><strong>0.96429</strong><span style="font-weight: 400;">,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">mAP_0.5 &#8211; </span><strong>0.94755</strong><span style="font-weight: 400;">,</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">mAP_0.5:0.95 &#8211;</span> <strong>0.48702</strong><span style="font-weight: 400;">,<br />
</span></li>
</ul>
<p><span style="font-weight: 400;">where:</span></p>
<p><i><span style="font-weight: 400;">precision</span></i><span style="font-weight: 400;"> &#8211; measures how accurate are your predictions,</span></p>
<p><i><span style="font-weight: 400;">recall </span></i><span style="font-weight: 400;">&#8211; measures how good you find all the positives,</span></p>
<p><i><span style="font-weight: 400;">mAP_0.5</span></i><span style="font-weight: 400;"> &#8211; mean average precision for IoU* = 0.5,</span></p>
<p><i><span style="font-weight: 400;">mAP_0.5:0.95</span></i><span style="font-weight: 400;"> &#8211; mean average precision for IoU* from 0.5 to 0.95 with a step size of 0.005,</span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">* IoU (</span><i><span style="font-weight: 400;">Intersection over Union</span></i><span style="font-weight: 400;">) &#8211; measures the overlap between 2 boundaries. Find out more about these metrics </span><a href="https://jonathan-hui.medium.com/map-mean-average-precision-for-object-detection-45c121a31173"><span style="font-weight: 400;">here</span></a><span style="font-weight: 400;">.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h4><span style="color: #800080;"><b>Inference on test images</b></span></h4>
<p>&nbsp;</p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />Now,</span> <span style="font-weight: 400;">when we have our trained model trained after the learning stage, we may go to inference on test images. As you remember, one of the directories exported from </span><i><span style="font-weight: 400;">Roboflow </span></i><span style="font-weight: 400;">was called </span><strong>test</strong><span style="font-weight: 400;">. We can use it by putting in the terminal following line: </span></p>
<p>&nbsp;</p>
<pre>python detect.py --weights best.pt --source dataset/test --conf 0.6 --img-size 600</pre>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">where </span><i><span style="font-weight: 400;">conf</span></i><span style="font-weight: 400;"> is model confidence &#8211; higher required makes fewer predictions. </span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">Finally, we may see the result visualization. The approximate inference time on one test image </span><strong>416&#215;416</strong><span style="font-weight: 400;"> was </span><strong><span style="color: #000000;">~ 0.3 s</span></strong><span style="font-weight: 400;">, while for </span><strong>700&#215;700 ~ 0.8s</strong><b>.</b></p>
<p><img loading="lazy" decoding="async" data-attachment-id="4936" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/inferencecomp-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/inferencecomp-1.gif" data-orig-size="1138,406" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inferencecomp" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/inferencecomp-1-300x107.gif" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/inferencecomp-1-1030x367.gif" tabindex="0" role="button" class="aligncenter wp-image-4936 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/inferencecomp-1.gif" alt="inference" width="1138" height="406" /><br />
<img loading="lazy" decoding="async" data-attachment-id="3309" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/10.png" data-orig-size="675,675" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="10" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/10-300x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/10.png" tabindex="0" role="button" class="aligncenter wp-image-3309 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/10.png" alt="signatures on invoice" width="675" height="675" srcset="https://inero-software.com/wp-content/uploads/2021/02/10.png 675w, https://inero-software.com/wp-content/uploads/2021/02/10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2021/02/10-300x300.png 300w, https://inero-software.com/wp-content/uploads/2021/02/10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2021/02/10-512x512.png 512w" sizes="(max-width: 675px) 100vw, 675px" /> <img loading="lazy" decoding="async" data-attachment-id="3313" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/inv_inference/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/inv_inference.jpg" data-orig-size="1236,416" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inv_inference" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/inv_inference-300x101.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/inv_inference-1030x347.jpg" tabindex="0" role="button" class="aligncenter wp-image-3313 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/inv_inference.jpg" alt="signatures on invoice" width="1236" height="416" srcset="https://inero-software.com/wp-content/uploads/2021/02/inv_inference.jpg 1236w, https://inero-software.com/wp-content/uploads/2021/02/inv_inference-300x101.jpg 300w, https://inero-software.com/wp-content/uploads/2021/02/inv_inference-768x258.jpg 768w, https://inero-software.com/wp-content/uploads/2021/02/inv_inference-1030x347.jpg 1030w, https://inero-software.com/wp-content/uploads/2021/02/inv_inference-891x300.jpg 891w" sizes="(max-width: 1236px) 100vw, 1236px" /> <img loading="lazy" decoding="async" data-attachment-id="3317" data-permalink="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/test_batch0_pred/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred.jpg" data-orig-size="1280,1280" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="test_batch0_pred" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-300x300.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-1030x1030.jpg" tabindex="0" role="button" class="aligncenter wp-image-3317 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred.jpg" alt="signatures on invoice" width="1280" height="1280" srcset="https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred.jpg 1280w, https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-80x80.jpg 80w, https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-300x300.jpg 300w, https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-768x768.jpg 768w, https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-1030x1030.jpg 1030w, https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-50x50.jpg 50w, https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-512x512.jpg 512w, https://inero-software.com/wp-content/uploads/2021/02/test_batch0_pred-1024x1024.jpg 1024w" sizes="(max-width: 1280px) 100vw, 1280px" /><br />
<img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h3><span style="color: #800080;"><b>Summary</b></span></h3>
<p>&nbsp;</p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />For the implementation of the described detector, we used only 10 images, extending the dataset by augmentation process. Thanks to the Roboflow tool, it was possible to quickly annotate and export the data to the YOLO format. The learning process allowed us to obtain a target detector that effectively recognizes signatures on invoices.</span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">Please note that with such a small dataset it is only adapted to recognize similar invoices. If we wanted to expand the possibilities of our detector, we would have to equip ourselves with a better graphics card and more, and more data. Additionally, you may be tempted to add a new class, e.g. to separate the objects into the Signature of the Seller and the Buyer.</span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">Maybe you will see a new article in the future with more recognition classes. Stay tuned!</span></p>
<p>&nbsp;</p>
<p><strong>In Inero Software &#8211; software development agency, we are experts of digital transformation and smart automation. We provide knowledge and expertise on how to successfully use cutting edge technologies and data to shape corporate digital products of the future.</strong></p>
<p>&nbsp;</p>
<p><strong>For more information, visit us on our <a href="https://inero-software.com">website</a> or follow us on <a href="https://www.linkedin.com/company/inero-software/">LinkedIn</a>. </strong></p>
<p>Artykuł <a href="https://inero-software.com/digital-cloud-document-repositories-how-to-identify-signatures-in-scanned-pdf-documents/">Digital Cloud Document Repositories &#8211; how to identify signatures in scanned PDF documents</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3306</post-id>	</item>
		<item>
		<title>Skoruba for Identity Server &#8211; a review of authorization module for .NET Applications</title>
		<link>https://inero-software.com/skoruba-for-identity-server-a-review-of-authorization-module-for-net-applications/</link>
		
		<dc:creator><![CDATA[Andrzej Chybicki]]></dc:creator>
		<pubDate>Wed, 03 Feb 2021 15:12:53 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[aspnetcore]]></category>
		<category><![CDATA[dotnetcore]]></category>
		<category><![CDATA[identityserver4]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[skoruba]]></category>
		<guid isPermaLink="false">https://sandbox-www.devel.inero.com.pl/?p=3272</guid>

					<description><![CDATA[<p>Artykuł <a href="https://inero-software.com/skoruba-for-identity-server-a-review-of-authorization-module-for-net-applications/">Skoruba for Identity Server &#8211; a review of authorization module for .NET Applications</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="row">
<p><div class="col-sm-3"></div></p>
<p><div class="col-sm-6">
<p>&nbsp;</p>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<p><span style="font-weight: 400;">.NET Core gives us a lot of possibilities in terms of building business solutions in the logistic, finance or banking sector. Among the most important advantages of this environment are built-in mechanisms of user authentication and authorization, enabling to build requests workflow relying on modules called middleware. These modules can be replaced, to change behavior of our application and way how the application handles incoming requests.</span></p>
<p><span style="font-weight: 400;">.NET Core also lets us protect our application against attacks such as: XSS, SQL Injection, CSRF or Open Redirect Attacks. Also, we can easily enforce the application to use HTTPS instead of less secure HTTP. Thanks to .NET Core developers can implement the authorization process in many ways, like: role-based authorization, claims-based or policies-based.</span></p>
<p><span style="font-weight: 400;">For the above reasons, .NET Core solutions are often used in big organizations, corporations and enterprises. Due to the huge amount of users and complicated business processes, these systems require complex and solid mechanisms to protect users accounts and to manage identities in our applications.</span></p>
<p><span style="font-weight: 400;">Therefore, in this short review post we will provide one the tools we utilized for secure authorization built for one of our corporate clients, namely .NET-based  <strong>Skoruba.IdentityServer4.Admin</strong> project.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h2><strong><span style="color: #800080;">What&#8217;s Skoruba?</span></strong></h2>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<p><span style="font-weight: 400;">Scoruba is an open-source project providing a user interface that allows for the administration of IdentityServer4 and ASP.NET Core Identity functionalities. Thanks to this project we are relieved in some way from creating the visual side of the functionality related to user management. </span><span style="font-weight: 400;">Main advantage of Scoruba project is the user-friendly interface, which relies on Bootstrap, and let&#8217;s us manage users, passwords, two-factor authentication, roles, clients, resources or structure of access tokens and their claims in a very efficient way.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="3282" data-permalink="https://inero-software.com/skoruba-for-identity-server-a-review-of-authorization-module-for-net-applications/ui2/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/UI2.png" data-orig-size="864,512" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="UI2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/UI2-300x178.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/UI2.png" tabindex="0" role="button" class="aligncenter wp-image-3282 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/UI2.png" alt="Skoruba IdentityServer4" width="864" height="512" srcset="https://inero-software.com/wp-content/uploads/2021/02/UI2.png 864w, https://inero-software.com/wp-content/uploads/2021/02/UI2-300x178.png 300w, https://inero-software.com/wp-content/uploads/2021/02/UI2-768x455.png 768w, https://inero-software.com/wp-content/uploads/2021/02/UI2-506x300.png 506w" sizes="(max-width: 864px) 100vw, 864px" /></p>
<p style="text-align: center;"><span style="font-weight: 400;">Source: https://github.com/skoruba/IdentityServer4.Admin</span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">In addition, Skoruba also provides an API that we can consume in any way and, on its basis, build the logic related to account management in a way that will better suit our business requirements. All documentation of this API is available thanks to Swagget, which also allows us to test individual actions of the API.</span></p>
<p><span style="font-weight: 400;">The ability to change the database provider in which we store all of the identity information is also easier and by default we have a choice of such providers as: SqlServer, MySql and PostgreSql.</span></p>
<p><span style="font-weight: 400;">Another advantage of the Skoruba is the very well developed mechanism of logging events in our application that is based on the Serilog library, which allows for very efficient identification of potential problems occurring while the application is running. You can see the Skoruba’s application visualisation below:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="3275" data-permalink="https://inero-software.com/skoruba-for-identity-server-a-review-of-authorization-module-for-net-applications/components/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/Components.png" data-orig-size="1514,686" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="AdminComponents" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/Components-300x136.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/Components-1030x467.png" tabindex="0" role="button" class="alignnone wp-image-3275 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/Components.png" alt="visualisation of skoruba" width="1514" height="686" srcset="https://inero-software.com/wp-content/uploads/2021/02/Components.png 1514w, https://inero-software.com/wp-content/uploads/2021/02/Components-300x136.png 300w, https://inero-software.com/wp-content/uploads/2021/02/Components-768x348.png 768w, https://inero-software.com/wp-content/uploads/2021/02/Components-1030x467.png 1030w, https://inero-software.com/wp-content/uploads/2021/02/Components-662x300.png 662w" sizes="(max-width: 1514px) 100vw, 1514px" /></p>
<p style="text-align: center;"><span style="font-weight: 400;">Source: https://github.com/skoruba/IdentityServer4.Admin</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h2><span style="font-weight: 400; color: #800080;">How Scoruba handles user roles? Example</span></h2>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />We can see here, how the section of interface where user roles can be modified looks like:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="3283" data-permalink="https://inero-software.com/skoruba-for-identity-server-a-review-of-authorization-module-for-net-applications/userroles2/" data-orig-file="https://inero-software.com/wp-content/uploads/2021/02/UserRoles2.png" data-orig-size="1137,817" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="UserRoles2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2021/02/UserRoles2-300x216.png" data-large-file="https://inero-software.com/wp-content/uploads/2021/02/UserRoles2-1030x740.png" tabindex="0" role="button" class="alignnone wp-image-3283 size-full" src="https://inero-software.com/wp-content/uploads/2021/02/UserRoles2.png" alt="Skoruba interface" width="1137" height="817" srcset="https://inero-software.com/wp-content/uploads/2021/02/UserRoles2.png 1137w, https://inero-software.com/wp-content/uploads/2021/02/UserRoles2-300x216.png 300w, https://inero-software.com/wp-content/uploads/2021/02/UserRoles2-768x552.png 768w, https://inero-software.com/wp-content/uploads/2021/02/UserRoles2-1030x740.png 1030w, https://inero-software.com/wp-content/uploads/2021/02/UserRoles2-418x300.png 418w" sizes="(max-width: 1137px) 100vw, 1137px" /></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">If we hadn&#8217;t used Scoruba, we&#8217;d have to create it all by ourselves including the logic and way how to present it in good manner. So, it gives us a lot of functions that we don’t have to create and be more focused on our business requirements instead of making the whole new user interface to handle IdentityServer4 and ASP.NET Core Identity services. The example logic that shows us how Scoruba generates user roles as presented above, is shown in the code-block below:</span></p>
<pre>public virtual async Task BuildUserRolesViewModel(TKey id, int? page)
{s
    var roles = await GetRolesAsync();
    var userRoles = await GetUserRolesAsync(id.ToString(), page ?? 1);
    userRoles.UserId = id;
    userRoles.RolesList = roles.Select(x =&gt; new SelectItemDto(x.Id.ToString(), x.Name)).ToList();

    return userRoles;
}

public virtual async Task GetUserRolesAsync(string userId, int page = 1, int pageSize = 10)
{
    var userExists = await IdentityRepository.ExistsUserAsync(userId);
    if (!userExists) throw new UserFriendlyErrorPageException(string.Format(IdentityServiceResources.UserDoesNotExist().Description, userId), 
    IdentityServiceResources.UserDoesNotExist().Description);

    var userIdentityRoles = await IdentityRepository.GetUserRolesAsync(userId, page, pageSize);
    var roleDtos = Mapper.Map(userIdentityRoles);

    var user = await IdentityRepository.GetUserAsync(userId);
    roleDtos.UserName = user.UserName;

    await AuditEventLogger.LogEventAsync(new UserRolesRequestedEvent(roleDtos));

    return roleDtos;
}
</pre>
<p><span style="font-weight: 400;">What’s more? If we wish, we can change the appearance of the interface if we want, because the whole page is made with RazorPages in MVC design pattern. We may also modify the content of the site by alternating the logic that will be accurate to our business needs.</span></p>
<p><span style="font-weight: 400;">If you need more information about the Scoruba project and its power just go to the project site on GitHub: </span><a href="https://github.com/skoruba/IdentityServer4.Admin"><span style="font-weight: 400;">https://github.com/skoruba/IdentityServer4.Admin</span></a><span style="font-weight: 400;"> </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h2><span style="font-weight: 400; color: #800080;">Summary</span></h2>
<p><span style="font-weight: 400;"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></span></p>
<p><span style="font-weight: 400;">In </span><a href="https://inero-software.com"><span style="font-weight: 400;">Inero Software &#8211; R&amp;D software house</span></a><span style="font-weight: 400;"> we deal with ambitious and demanding software development projects. In this blog post we showed how quickly one can use ready-to-use existing open-source solutions to provide an efficient way of implementing software security. Apart from presented use-case, Scoruba and Identity Server can be also used for working with mobile devices, IoT systems or withing a M2M communication between machines or robots.</span></p>
<p><span style="font-weight: 400;">If you want to know more about us or more about how to transform business needs to reliable digital products, visit our blog or read more about us on our webpage:</span></p>
<p><span style="font-weight: 400;"><a href="https://inero-software.com">https://inero-software.com</a> or on our blog site: <a href="https://inero-software.com/category/blog/company/">https://inero-software.com/category/blog/company/</a></span></p>
<p>&nbsp;</p>
<p></p></div><br />
</p></div>
<p>Artykuł <a href="https://inero-software.com/skoruba-for-identity-server-a-review-of-authorization-module-for-net-applications/">Skoruba for Identity Server &#8211; a review of authorization module for .NET Applications</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3272</post-id>	</item>
		<item>
		<title>RxJs for beginners (5 most useful operators)</title>
		<link>https://inero-software.com/rxjs-for-beginners-5-most-useful-operators/</link>
		
		<dc:creator><![CDATA[Waldemar Korłub]]></dc:creator>
		<pubDate>Thu, 26 Nov 2020 12:45:44 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[angular]]></category>
		<category><![CDATA[DOM event]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[Http request]]></category>
		<category><![CDATA[Observable]]></category>
		<category><![CDATA[Operator]]></category>
		<guid isPermaLink="false">https://sandbox-www.devel.inero.com.pl/?p=3159</guid>

					<description><![CDATA[<p>This time we’re going to take a look at RxJs operators, what they do, and how you should (or shouldn’t) use it. In case you decide that in fact you want to use it then you can read the rest of the article where I go over most common use&#8230;</p>
<p>Artykuł <a href="https://inero-software.com/rxjs-for-beginners-5-most-useful-operators/">RxJs for beginners (5 most useful operators)</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div style="padding-top: 1rem;">This time we’re going to take a look at RxJs operators, what they do, and how you should (or shouldn’t) use it. In case you decide that in fact you want to use it then you can read the rest of the article where I go over most common use cases and usage examples.</div>
<p>WARNING: I assume that you know basics of asynchronous programming, if not then please read this before going any further: <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">Asynchronous Concepts</a></p>
<h3><span style="color: #511b73;"><b>So, what’s RxJs?</b></span></h3>
<p>According to the documentation:</p>
<blockquote><p>RxJS is a library for composing asynchronous and event-based programs by using observable sequences. It provides one core type, the Observable, satellite types (Observer, Schedulers, Subjects) and operators inspired by Array#extras (map, filter, reduce, every, etc) to allow handling asynchronous events as collections.</p></blockquote>
<p>In simple words, RxJs is a library which helps you in working with asynchronous tasks, events and streams and it does that by sharing some useful classes like aforementioned <em>Observable</em> and a ton of cool operators (due to my desire of keeping this post relatively short I am going to present only 5 operators that I find the most useful in my everyday work). Actually, RxJs has been so helpful to the Angular community that the Angular team decided to include it into Angular itself with the 6th version.</p>
<p>We are going to focus on <em>Observables</em> this time. <em>Observable</em> is a class that allows you to listen for events. To retrieve data from an <em>observable</em> you need to subscribe to it, when you do that it listens for events happening, so when they happen, you get the data. You can get more details on <em>observables</em> here: https://rxjs.dev/guide/observable.</p>
<p>Now let’s discuss 3 most common situations where developers are using <em>Observables</em></p>
<h4><span style="color: #511b73;"><b>Http Requests</b></span></h4>
<p>All HtttpClient methods are returning Observables and that is of course because it takes time for a server to process and return the data (or just return in case you’re sending a <em>get</em> request). That means that http request operation is asynchronous.</p>
<h4><span style="color: #511b73;"><b>DOM events</b></span></h4>
<p>Observables enable you to easily listen for DOM events like <em>click</em> or <em>keyup</em>. To listen to them you should use the <em>fromEvent</em> function that creates an <em>observable</em> accordingly. Here’s how this looks like:</p>
<p>fromEvent(document, &#8216;keyup&#8217;);</p>
<p>(Remember that if you want to receive the actual data you should subscribe to it by adding .subscribe() before semicolon)</p>
<h4><span style="color: #511b73;"><b>Stores</b></span></h4>
<p>Another very common use case for using <em>Observables</em> is using them with some kind of store, like NgRx or NgXs. Stores like that usually share observables in order to keep watch over the state of the application.</p>
<p>Now since you know the very basics like why and how, let’s get to the useful interesting stuff that can be one with RxJs operators.</p>
<h3><span style="color: #511b73;"><b>RxJs o</b></span><span style="color: #511b73;"><b>perators</b></span></h3>
<p>In our examples we are going to use simplest observable possible:</p>
<pre>const obs$ = from([1, 2, 3]); (dollar sign at the end of the variable is a naming convention used to singlaize that the variable is indeed an observable)
</pre>
<h4><span style="color: #511b73;"><b>How to use operators?</b></span></h4>
<p>Easiest way to use operators is by putting them inside a pipe. Pipe runs a function for every stream element passing by the operator, and operators are the functions that can be used within it.</p>
<h5><span style="color: #511b73;"><b>first</b></span></h5>
<p><em>First</em> operator is the first operator that we’re going to talk about (got the pun?). Most operators have self-describing titles and this case is no different. <em>First</em> operator basically allows you to listen for the first returned value of the <em>observable</em> and then stop (note that it is completely useless combined with Http requests that return the value once anyways)</p>
<pre>obs$.pipe(first()).subscribe(numbr =&gt; console.log(number));
</pre>
<p>Code above prints only 1 because it’s the first event emitted, 2 and 3 are ignored.</p>
<h5><span style="color: #511b73;"><b>tap</b></span></h5>
<p>Another useful operator worth mentioning is <em>tap</em>. Tap allows you to perform some kind of side effect for every event emission. For example you can log something or assign data to a variable (note: if you are using .subscribe it is basically the same thing).</p>
<pre>obs$.pipe(tap(numbr =&gt; console.log(number))).subscribe();
</pre>
<p>Code above prints 1, 2 and 3 because <em>tap</em> is triggered for every emitted value.</p>
<h5><span style="color: #511b73;"><b>map</b></span></h5>
<p><em>Map</em> is working the same way as in arrays. So it basically allows you to change structure of returned data. For example, let’s try to multiply every value returned by 2</p>
<pre>obs$.pipe(map(numbr =&gt; numbr * 2)).subscribe(value =&gt; console.log(value));
</pre>
<p>The code prints 2, 4 and 6 just as expected.</p>
<h5><span style="color: #511b73;"><b>startWith</b></span></h5>
<p><em>StartWIth</em> allows you to decide what first value is going to be. It is useful when you want to trigger the observable before the first event emission.</p>
<pre>obs$.pipe(startWith(999)).subscribe(value =&gt; console.log(value));
</pre>
<p>Printed values are: 999, 1, 2, 3.</p>
<h5><span style="color: #511b73;"><b>switchMap</b></span></h5>
<p><em>SwitchMap</em> is used mainly in typeahead cases but not limited to them. What it does &#8211; it cancels previous request when a new event arrives. In real life case you would for example listen for changes on the input and filter a table while typing (previous result is not relevant).<br />
To present switchMap fully &#8211; this time we are going to use a different example. <em>Observable</em> is going to be created out of DOM event keyup.</p>
<pre>const another$ = timer(1000);
fromEvent(document, 'keyup').pipe(
switchMap(() =&gt; another$)
).subscribe(() =&gt; console.log('log'));
</pre>
<p>What happens here is: After you click a button on keyboard, wait 1000 ms and then log a message. Now what happens ,if you click button 10 times quicker? Only one message is going to be logged, and that is because switchMap cancels previous timers leaving only the most recent one.</p>
<p>We went over 5 most useful operators in my opinion, described what RxJs is and discussed common use cases. I hope that this article will help you in your next project and interest you in exploring RxJs more 🙂</p>
<p><a href="https://inero-software.com/contact-us/"><strong><span style="color: #800080;">Inero Software</span></strong></a> provides knowledge and expertise on how to successfully use cutting edge technologies and data to shape corporate digital products of the future.</p>
<p><span data-contrast="auto">In the <a href="https://inero-software.com/category/blog/company/"><strong><span style="color: #800080;">blog post</span></strong></a> section, you can find other articles about our projects and more!</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p>Artykuł <a href="https://inero-software.com/rxjs-for-beginners-5-most-useful-operators/">RxJs for beginners (5 most useful operators)</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3159</post-id>	</item>
		<item>
		<title>Java: Scheduling the execution of background tasks using Spring</title>
		<link>https://inero-software.com/java-scheduling-the-execution-of-background-tasks-using-spring/</link>
		
		<dc:creator><![CDATA[Adrian Chojnacki]]></dc:creator>
		<pubDate>Wed, 04 Nov 2020 08:47:18 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[angular]]></category>
		<category><![CDATA[asynchronous]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[big data]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[Quartz]]></category>
		<guid isPermaLink="false">https://sandbox-www.devel.inero.com.pl/?p=3123</guid>

					<description><![CDATA[<p>Artykuł <a href="https://inero-software.com/java-scheduling-the-execution-of-background-tasks-using-spring/">Java: Scheduling the execution of background tasks using Spring</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3></h3>
<div class="row"><div class="col-sm-4"></div><div class="col-sm-8">
<h3><span style="color: #800080;"><strong>Planning tasks in Java</strong></span></h3>
<p><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /><a href="https://inero-software.com/angular-how-to-manage-back-end-long-running-asynchronous-tasks/">In the last post by my teammate we presented how to manage back-end long-running asynchronous tasks from the client side.</a> This approach is used especially in handling the appropriate flow of processes and the timely implementation of specific IT system services that require significant amount of computations. From the backend implementation perspective, one of the libraries that enable task scheduling and easy integration with Java Spring applications is Quartz. In the following sections of the article, the general problem of running background tasks and a use case presenting an example solution will be described.</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h3><span style="color: #800080;"><strong>Description of the problem</strong></span></h3>
<p><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />In some cases, the specification of an IT system requires long-running tasks to be performed in background. Compared to synchronous jobs where we wait for output, background jobs allow us to move on to the next job before our primary task is finished. This can be achieved by executing independent tasks in separate threads, which inform the main thread of the application when particular background job is completed. In this case, one thread can be a code block or a method that is a separate unit of work.</p>
<p>The advantages of asynchronous job scheduling tasks include:</p>
<ul>
<li>application performance,</li>
<li>responsiveness and scalability,</li>
<li>the ability to update the progress or parameters of the task,</li>
<li>productive planning of service delivery,</li>
<li>the ability to perform the following tasks without freezing the application state.</li>
</ul>
<p>However, when running background, it is important to remember to skillfully choose between asynchronous and synchronous programming. If You are dealing with simple, short-lived calculations, it is not a good idea to use background tasks. For instance, too many asynchronous calls between main thread and background can make your code less readable, may cause slow application performance or even lead to thread lock and interrupt application lifecycle.</p>
<p>Check out how we deal with such problems in our team.</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h3><span style="color: #800080;"><strong>Use case, solution</strong></span></h3>
<p><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />In this post, as an example of using asynchronous programming, we will use a big data download service. Let us assume that a potential user of our website would like to transfer a certain number of files using logic provided by our backend application. As it is presented in the diagram below, the user interface allows to execute task that starts to transfer the file via request made to application server. Since we expect that this task will be a long running one, our goal is to schedule this job to be performed in background thread. Let&#8217;s have a look at details:</p>
<p>&nbsp;</p>
<h3><span style="color: #800080;"><strong><img loading="lazy" decoding="async" data-attachment-id="3139" data-permalink="https://inero-software.com/java-scheduling-the-execution-of-background-tasks-using-spring/tasks/" data-orig-file="https://inero-software.com/wp-content/uploads/2020/10/tasks.png" data-orig-size="1294,370" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="tasks" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2020/10/tasks-300x86.png" data-large-file="https://inero-software.com/wp-content/uploads/2020/10/tasks-1030x295.png" tabindex="0" role="button" class="aligncenter wp-image-3139 size-full" src="https://inero-software.com/wp-content/uploads/2020/10/tasks.png" alt="A drawing about how the interface works" width="1294" height="370" srcset="https://inero-software.com/wp-content/uploads/2020/10/tasks.png 1294w, https://inero-software.com/wp-content/uploads/2020/10/tasks-300x86.png 300w, https://inero-software.com/wp-content/uploads/2020/10/tasks-768x220.png 768w, https://inero-software.com/wp-content/uploads/2020/10/tasks-1030x295.png 1030w, https://inero-software.com/wp-content/uploads/2020/10/tasks-1049x300.png 1049w" sizes="(max-width: 1294px) 100vw, 1294px" /></strong></span></h3>
<p>In applications based on <a href="https://spring.io/">Spring</a>, the aforementioned Quartz library is the perfect choice. It allows you to schedule tasks depending on our needs.</p>
<p>Let&#8217;s make the following assumptions:</p>
<ul>
<li>the user can order to download several files at a time,</li>
<li>in this case, the tasks will be performed sequentially,</li>
<li>the user can  (interrupt) tasks,</li>
<li>user is provided with information about tasks, such as <em>id</em> or user data, in the database.</li>
</ul>
<p>Note that with the use of Quartz, you can execute threads simultaneously, but for the purpose of this post will used the task queue. The key interfaces used in this API are <em>Scheduler</em>, <em>Job, JobDetail, JobDataMap, Trigger</em>.</p>
<p>Initially, you need to create a <em>Scheduler</em> instance as the main interaction component. This can be done by injection into a class or by using the lines of code below.</p>
<pre>SchedulerFactory schedulerFactory = new StdSchedulerFactory();
Scheduler scheduler = schedulerFactory.getScheduler();</pre>
<p>The next step is to define an example class, in this case <em>FileDownloadJob</em>, extended by the <em>QuartzJobBean</em> class, which implements the <em>Job</em> interface. The main method <em>executeInternal()</em>,  will be called by one of the <em>Scheduler</em> threads after the <em>Trigger</em> is fired. Inside it, the target action of a given task should be performed.</p>
<pre>public class FileDownloadJob extends QuartzJobBean {

   @Override
   protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionExceptions{
       // target code of performed operations
   }
}
</pre>
<p>The job scheduling process consists of assigning a unique key &#8220;<em>JobKey&#8221;</em>, preparing a <em>JobDataMap</em> and building a<em> JobDetail</em> instance. Assuming the &#8220;<em>task&#8221;</em> object is one of the records in the task database repository, the operations in question can be performed with the following lines of code.</p>
<pre>JobKey jobKey = JobKey.jobKey((task.getId());
</pre>
<pre>JobDataMap jobData = new JobDataMap();
jobData.putAll(new HashMap&lt;&gt;() {{
 	  put("email", user.getEmail());
  	  put("name", user.getName());
          put("progress", task.getProgress());
}});
</pre>
<pre>JobDetail jobDetail = newJob().ofType(FileDownloadJob.class)
       				.withIdentity(jobKey)
      				.setJobData(jobData)
      				.build();
</pre>
<p>If we have all the details, we can fire the trigger and plan our task.</p>
<pre>Trigger trigger = newTrigger()
       .startNow()
       .build();

scheduler.scheduleJob(jobDetail, trigger);
</pre>
<p>Returning to the assumptions of the solution, consider the possibility of deleting tasks. In the Quartz library it is possible to additionally implement the <em>InterruptableJob</em> interface in our job class.</p>
<pre>public class FileDownloadJob extends QuartzJobBean implements InterruptableJob</pre>
<p>It implements the <em>interrupt()</em> method where we can stop the job.</p>
<pre>@Override
public void interrupt() {
   _interrupted = true;
}
</pre>
<p>Assuming that the operations performed inside the job are carried out in a loop, we can check the given <em>_interrupted</em> field, and for example if it is equal to <em>True</em>, terminate the job.</p>
<pre>if (_interrupted) {
   break;
}
</pre>
<p>Of course, this is just an example of a job interruption. It is fully dependent on the operations performed within the method of execution. From the <em>Scheduler</em> side, the method shown below allows us to call the <em>interrupt()</em> method inside our <em>FileDownloadJob</em> class.</p>
<pre>scheduler.interrupt(jobKey);
</pre>
<p>Another functionality is the sequential execution of tasks. This can be implemented in various ways, such as <em>JobListener</em> or smart use of <em>JobDataMap</em>. In our use case, we choose the second option, due to the possibility of further expansion, i.e. updating progress, stopping and resuming tasks.<br />
Let&#8217;s add another field in our map and fill it with the <em>id</em> of the next job, assuming that all information about the tasks is stored in the database.</p>
<pre>jobDataMap.put("nextJob", nextTask.getId());
</pre>
<p>Thanks to this, when we finish the operation of the first job, we can check if there is a unique key in the &#8220;<em>nextJob&#8221;</em> field of <em>JobDataMap</em>. If so, we move on to the next task. If we would like to add the functionality of changing the order of task execution, we could define another &#8220;<em>previousTask&#8221;</em> field storing the <em>id</em> of the previous task. Based on this, we could define appropriate methods to modify the queue position. In addition, in our map we can store the previously mentioned information about the current data download process and update it via REST endpoints in the client interface.</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h3><span style="color: #800080;"><strong>Java Scheduling &#8211; Summary</strong></span></h3>
<p>Asynchronous programming is an essential element in delivering some IT system services. However, it should be remembered that the use of background tasks should be carefully selected for the problem in order to avoid unnecessary conflicts or system overload. If you are using Java, the Quartz library is a good choice that allows you to easily integrate the planning process with our application. Try this!</p>
<p></p></div><div class="col-sm-4"></div></div>
<h3></h3>
<p>Artykuł <a href="https://inero-software.com/java-scheduling-the-execution-of-background-tasks-using-spring/">Java: Scheduling the execution of background tasks using Spring</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">3123</post-id>	</item>
		<item>
		<title>Few tips on how to create custom class detection system using R-CNN</title>
		<link>https://inero-software.com/few-tips-on-how-to-create-custom-class-detection-system-using-r-cnn/</link>
		
		<dc:creator><![CDATA[Adrian Chojnacki]]></dc:creator>
		<pubDate>Mon, 28 Sep 2020 12:46:24 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Artificial Intelligence]]></category>
		<category><![CDATA[Deep learning]]></category>
		<category><![CDATA[Image processing]]></category>
		<category><![CDATA[Keras]]></category>
		<category><![CDATA[Machine Learning]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[R-CNN-based detectors]]></category>
		<category><![CDATA[Tensorflow]]></category>
		<guid isPermaLink="false">https://sandbox-www.devel.inero.com.pl/?p=2973</guid>

					<description><![CDATA[<p>Region based Convolutional Neural Network &#8211; R- CNN Thanks to the development of computing technology and artificial intelligence in recent years, applications using machine learning and systems based on neural networks have more and more business uses. Moreover, the advancement of technology has made machine learning, adapting advanced solutions based&#8230;</p>
<p>Artykuł <a href="https://inero-software.com/few-tips-on-how-to-create-custom-class-detection-system-using-r-cnn/">Few tips on how to create custom class detection system using R-CNN</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h3><span style="color: #800080;"><strong>Region based Convolutional Neural Network &#8211; R- CNN</strong></span></h3>
<p><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<p><span data-contrast="none">Thanks to the development of computing technology and artificial intelligence in recent years, applications using machine learning and systems based on neural networks have more and more business uses. Moreover, the advancement of technology has made machine learning, adapting advanced solutions based on neural networks cheaper and allows for relatively quick creation of solutions that have direct application, such as tracking objects on the camera image (tracking cars in parking lots, detecting people on construction sites) or extracting information from scans of documents (finding amounts and contractor data on an invoice).</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559731&quot;:708,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><span data-contrast="none">In the described material, we presented the methodology that we use as part of o<a href="https://sandbox-www.devel.inero.com.pl/machine-learning-professionals/">ur ML-based work using R-CNN networks</a>, which due to the universality of the structure and architecture of the model, work well in a wide range of areas. It is a type of neural network specifically designed to detect objects, </span><span data-contrast="auto">which at least one layer is a convolution layer, allowing to distinguish the features of the manipulated image. </span><span data-contrast="none">Based on the input image, R-CNN determines potential ROI&#8217;s (regions of interest) by selective search segmentation. Then each of them is analyzed by a neural network to obtain the probability of the object classification.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559731&quot;:708,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><span data-contrast="none">R-CNN detectors are widely used in:</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="9" aria-setsize="-1" data-aria-posinset="1" data-aria-level="1"><span data-contrast="none">driver assistance systems in autonomous cars,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="9" aria-setsize="-1" data-aria-posinset="2" data-aria-level="1"><span data-contrast="none">face recognition,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="9" aria-setsize="-1" data-aria-posinset="3" data-aria-level="1"><span data-contrast="none">anomalies detection, </span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="9" aria-setsize="-1" data-aria-posinset="4" data-aria-level="1"><span data-contrast="none">health risk assessment and biomarkers of aging discovery</span><b><span data-contrast="none">, </span></b></li>
<li data-leveltext="" data-font="Symbol" data-listid="9" aria-setsize="-1" data-aria-posinset="4" data-aria-level="1"><span data-contrast="none">Intelligent multi-site surveillance system,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
</ul>
<p><span data-contrast="none">and many others&#8230;</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><span data-contrast="none">Building your own R-CNN detector is a simple task that does not require a lot of work. In this article you will see an example of its use and the next steps in the process.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h3><strong><span style="color: #800080;">Use case</span></strong></h3>
<p><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<p><span class="TextRun SCXW212057878 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="none"><span class="NormalTextRun SCXW212057878 BCX0">In order to demonstrate the possibility of building Your own detector based on R-CNN, the use case in this article will be the date detection on the transport document. Your solution may have different elements or the number of classes of objects to be recognized. A sample document is shown in the illustration below. As You can see, there are many irrelevant elements on this picture. In this case, we are only interested on each date.</span></span><span class="EOP SCXW212057878 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559685&quot;:12,&quot;335559731&quot;:708,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2986" data-permalink="https://inero-software.com/few-tips-on-how-to-create-custom-class-detection-system-using-r-cnn/glass-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2020/09/glass-1.jpg" data-orig-size="946,439" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="glass" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2020/09/glass-1-300x139.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2020/09/glass-1.jpg" tabindex="0" role="button" class="aligncenter wp-image-2986 size-full" src="https://inero-software.com/wp-content/uploads/2020/09/glass-1.jpg" alt="set of data" width="946" height="439" srcset="https://inero-software.com/wp-content/uploads/2020/09/glass-1.jpg 946w, https://inero-software.com/wp-content/uploads/2020/09/glass-1-300x139.jpg 300w, https://inero-software.com/wp-content/uploads/2020/09/glass-1-768x356.jpg 768w, https://inero-software.com/wp-content/uploads/2020/09/glass-1-646x300.jpg 646w" sizes="(max-width: 946px) 100vw, 946px" /></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h3><span style="color: #800080;"><strong>Software architecture</strong></span></h3>
<p><span data-contrast="none">Programming tools enabling the implementation of the system in Python are, for example:</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559685&quot;:12,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="5" aria-setsize="-1" data-aria-posinset="1" data-aria-level="1"><i><span data-contrast="none">Tensorflow</span></i><span data-contrast="none">,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="5" aria-setsize="-1" data-aria-posinset="2" data-aria-level="1"><i><span data-contrast="none">Keras</span></i><span data-contrast="none">,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="5" aria-setsize="-1" data-aria-posinset="1" data-aria-level="1"><i><span data-contrast="none">OpenCV,</span></i><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="5" aria-setsize="-1" data-aria-posinset="2" data-aria-level="1"><i><i><span data-contrast="none">Scikit-learn. </span></i></i></li>
</ul>
<p><span data-contrast="none">Once we have configured development environment, the first step in building the system is collecting the dataset. In order to make a R-CNN based detector with a high measure of accuracy, remember that:</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="4" aria-setsize="-1" data-aria-posinset="3" data-aria-level="1"><span data-contrast="none">the collection of images must be extensive and diverse,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="4" aria-setsize="-1" data-aria-posinset="4" data-aria-level="1">as input to the model must be of the same dimension,</li>
<li data-leveltext="" data-font="Symbol" data-listid="4" aria-setsize="-1" data-aria-posinset="4" data-aria-level="1"><span data-contrast="none">eliminate duplicates that can cause network over-matching</span><span data-contrast="none">.</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
</ul>
<p><span data-contrast="none">For a good start, in the described case of the article it is enough to prepare even a few photos of the elements that we want to recognize, preferably against the background of other objects. Why such preferences? In the next step of the algorithm, </span><span data-contrast="none">should be </span><span data-contrast="none">a positiv</span><span data-contrast="none">e and negative samples</span><span data-contrast="none"> generated from the prepared set.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><span data-contrast="none">In order to generate the samples, we will use selective search segmentation.  The possibility of using this algorithm is provided by the </span><i><span data-contrast="none">OpenCV</span></i><span data-contrast="none"> library.  This function uses hierarchical clustering to group pixels and then combine them into one based on color, texture or composition. The following is an implementation of the search code on the base image. The output of the process is a set of a potential ROI’s, depending on the size of the photo, even over 2.000 item’s. </span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<pre>selective_search = cv2.ximgproc.segmentation.createSelectiveSearchSegmentation()
selective_search.setBaseImage(image)
selective_search.switchToSelectiveSearchFast()
rects = selective_search.process()</pre>
<p><span class="TextRun SCXW43619007 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW43619007 BCX0">To divide the generated ROI’s, for example, we can use a metric called IoU (Intersection over Union). It’s defined as the intersection area divided by area of the union of a predicted bounding box and ground-truth box. Using this factor will allow You to filter when building a sample set. However, before we proceed to this operation, You should manually prepare the ground truth.  There are many different object tagging programs available on the internet. In this article, we will use the VoTT (Visual object Tagging Tool)</span></span><span class="TextRun SCXW43619007 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW43619007 BCX0"> originally developed by the Commercial Software Engineering (CSE) group at Microsoft</span></span><span class="TextRun SCXW43619007 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW43619007 BCX0">. </span></span><span class="EOP SCXW43619007 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2987" data-permalink="https://inero-software.com/few-tips-on-how-to-create-custom-class-detection-system-using-r-cnn/vott-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2020/09/vott-1.jpg" data-orig-size="1920,998" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="vott" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2020/09/vott-1-300x156.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2020/09/vott-1-1030x535.jpg" tabindex="0" role="button" class="aligncenter wp-image-2987 size-full" src="https://inero-software.com/wp-content/uploads/2020/09/vott-1.jpg" alt="Software architecture" width="1920" height="998" srcset="https://inero-software.com/wp-content/uploads/2020/09/vott-1.jpg 1920w, https://inero-software.com/wp-content/uploads/2020/09/vott-1-300x156.jpg 300w, https://inero-software.com/wp-content/uploads/2020/09/vott-1-768x399.jpg 768w, https://inero-software.com/wp-content/uploads/2020/09/vott-1-1030x535.jpg 1030w, https://inero-software.com/wp-content/uploads/2020/09/vott-1-577x300.jpg 577w" sizes="(max-width: 1920px) 100vw, 1920px" /></p>
<p><span class="TextRun SCXW267799848 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267799848 BCX0">The above image shows the tagged date in the sample photo.  The operation should be repeated for all prepared data and exported to the appropriate format (JSON, XML, etc.). The generated files contain the exact coordinates and labels of previously marked objects. This allows us to compare our tagge</span></span><span class="TextRun SCXW267799848 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267799848 BCX0">d</span></span><span class="TextRun SCXW267799848 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267799848 BCX0"> data with those that will return a selective search segmentation. In this algorithm, we decided to set the IOU to 0.5</span></span><span class="TextRun SCXW267799848 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267799848 BCX0">, because of the good prediction result</span></span><span class="TextRun SCXW267799848 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267799848 BCX0">.</span></span><span class="TextRun SCXW267799848 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267799848 BCX0"> You can modify this ratio depending on Your preferences and check whether the resulting data set is consistent with the assumptions.</span></span><span class="TextRun SCXW267799848 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267799848 BCX0"> After executing the script, the filtered data should look like this (on the left – positives, on the right – negatives). </span></span><span class="EOP SCXW267799848 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2976" data-permalink="https://inero-software.com/few-tips-on-how-to-create-custom-class-detection-system-using-r-cnn/samples/" data-orig-file="https://inero-software.com/wp-content/uploads/2020/09/samples.png" data-orig-size="1796,722" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Positi" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2020/09/samples-300x121.png" data-large-file="https://inero-software.com/wp-content/uploads/2020/09/samples-1030x414.png" tabindex="0" role="button" class="aligncenter wp-image-2976 size-full" src="https://inero-software.com/wp-content/uploads/2020/09/samples.png" alt="set of data" width="1796" height="722" srcset="https://inero-software.com/wp-content/uploads/2020/09/samples.png 1796w, https://inero-software.com/wp-content/uploads/2020/09/samples-300x121.png 300w, https://inero-software.com/wp-content/uploads/2020/09/samples-768x309.png 768w, https://inero-software.com/wp-content/uploads/2020/09/samples-1030x414.png 1030w, https://inero-software.com/wp-content/uploads/2020/09/samples-746x300.png 746w" sizes="(max-width: 1796px) 100vw, 1796px" /></p>
<p><span data-contrast="auto">As You can see, the positive samples present a variety of dates, while the negative other </span><span data-contrast="auto">image elements.  On such a data</span><span data-contrast="auto">set, we can move on to building the R-CNN neural network model. A helpful library in this aspect will be the previously mentioned </span><i><span data-contrast="auto">Tensoflow </span></i><span data-contrast="auto">with </span><i><span data-contrast="auto">Keras</span></i><span data-contrast="auto">. </span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><span data-contrast="auto">After loading samples of the created model architecture You should split into test and training data. We can quickly do this with a single line of code using s</span><i><span data-contrast="auto">cikit-learn, </span></i><span data-contrast="auto">when we can define the size of the test data (</span><i><span data-contrast="auto">test_size) </span></i><span data-contrast="auto">and the shuffle value </span><i><span data-contrast="auto">(random_state).</span></i><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<pre>(self.train_x, self.test_x, self.train_y, self.test_y) = train_test_split(self.data, self.labels,
                                                                                  test_size=0.1,
                                                                                  stratify=self.labels,
                                                                                  random_state=42)</pre>
<p><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0">The </span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0">Tensorflow</span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0"> library is already so extensive that it provides us with ready-made network architectures. </span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0">The</span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0"> implemented algorithm uses the </span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0">MobileNetV2 </span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0">model, containing pre-trained weights from </span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0">ImageNet.</span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0"> </span></span><span class="TextRun SCXW19720123 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW19720123 BCX0">Here we define the dimension of each tensor, i.e. in this case the image, which is the input of the model.</span></span><span class="EOP SCXW19720123 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<pre>self.model = MobileNetV2(weights="imagenet", include_top=False, input_tensor=Input(shape=(224, 224, 3)))</pre>
<p><span data-contrast="auto">To the ready model architecture, optionally we can add layers to improve the network. In this use case have been used:</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="3" aria-setsize="-1" data-aria-posinset="1" data-aria-level="1"><i><span data-contrast="auto">pooling – </span></i><span data-contrast="auto">combining </span><span data-contrast="auto">the spatial data created by the convolution layer, minimizing the input data in both dimensions</span><i><span data-contrast="auto">,</span></i><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="3" aria-setsize="-1" data-aria-posinset="2" data-aria-level="1"><i><span data-contrast="auto">flatten – </span></i><span data-contrast="auto">minimazing each tensor to one dimensional,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="3" aria-setsize="-1" data-aria-posinset="3" data-aria-level="1"><i><span data-contrast="auto">dense</span></i><span data-contrast="auto"> – </span><span data-contrast="auto">enabling the connection of nodes in each subsequent layer using the activation function,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
</ul>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="3" aria-setsize="-1" data-aria-posinset="1" data-aria-level="1"><i><span data-contrast="auto">droput – </span></i><span data-contrast="auto">consisting in a random data rejection. Allows for regularization to prev</span><span data-contrast="auto">ent overfitting. It also proved</span><span data-contrast="auto"> the flexibility of the neural network and </span><span data-contrast="auto">the </span><span data-contrast="auto">margin of response to input data. </span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
</ul>
<p><span data-contrast="auto">The next step in creating Your own R-CNN based detector is to compile the model with defined optimizer, metrics and loss function. </span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<pre>self.model.compile(loss="binary_crossentropy", optimizer=Adam(lr=self.lr), metrics=["accuracy"])</pre>
<p><span data-contrast="auto">This algorithm uses the Adam’s optimizer, the acurracy metric and the loss function </span><i><span data-contrast="auto">binary crossentropy.</span></i><span data-contrast="auto"> </span><span data-contrast="auto">The selected parameters are popular for similar use ca</span><span data-contrast="auto">ses, but i</span><span data-contrast="auto">n the detailed </span><i><span data-contrast="auto">Tensorflow</span></i><span data-contrast="auto"> documentation you can find something specific</span><span data-contrast="auto"> for Your </span><span data-contrast="auto">solution.</span><span data-contrast="auto"> </span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><span data-contrast="auto">Now we can proceed to the training process. By properly defining the parameters of a function, we can do it with a line of code: </span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559731&quot;:708,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<pre>self.model.fit(
    x=None, y=None, batch_size=None, epochs=1, verbose=1, callbacks=None,
    validation_split=0.0, validation_data=None, shuffle=True, class_weight=None,
    sample_weight=None, initial_epoch=0, steps_per_epoch=None,
    validation_steps=None, validation_batch_size=None, validation_freq=1,
    max_queue_size=10, workers=1, use_multiprocessing=False
)</pre>
<p><span data-contrast="auto">Remember to choose the right learning parameters. Each epoch is modified with indivudal weights, which affects the quality of the network. In the algorithm results section of this article, You can see the parameters we selected and information on how to modify them.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><span data-contrast="auto">After completing the network training process, it is enough to save the model to a file and proceed to the next stage, i.e. object detection on test data. Now, for each input image, we once again perform a selective search segmentation and use the built-in model to predict individual ROI’s. For our own solution, we can define a minimum probability for which the regions will be considered valid. Typically, this value is in the range of 95-99%. Finally, all ROI’s that were filtered out in the previous operations can be </span><span data-contrast="auto">marked</span><span data-contrast="auto"> on the target image by using simple function of the </span><i><span data-contrast="auto">OpenCV</span></i><span data-contrast="auto"> library. </span><span data-contrast="auto">The next chapter presents the effects of the R-CNN based detector constructed in this article.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<h3><span style="color: #800080;">Results and summary</span></h3>
<p><span class="TextRun SCXW267551755 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267551755 BCX0"><img loading="lazy" decoding="async" data-attachment-id="2873" data-permalink="https://inero-software.com/digital-twins-a-dynamic-software-model-of-reality/inero-glify-08-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="inero-glyph" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png" tabindex="0" role="button" class="alignleft wp-image-2873 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png" alt="Paragraph icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/10/inero-glify-08.png 208w" sizes="(max-width: 80px) 100vw, 80px" />To implement detecor in this article were used only 10 images. It allowed to generate about 150 positive and 1000 negative samples. An important aspect of the network training itself is the selection of parameters. These include learning rate, batch size and number of epochs. The </span></span><span class="TextRun SCXW267551755 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267551755 BCX0">Tensorflow</span></span><span class="TextRun SCXW267551755 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267551755 BCX0"> library provides tools for evaluating the solution, such as </span></span><span class="TextRun SCXW267551755 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267551755 BCX0">Tensorboard</span></span><span class="TextRun SCXW267551755 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW267551755 BCX0"> or the classification report. In the first one, we can observe different types of graphs, such as the accuracy and loss of the learning process every epoch. Additionally, the report automatically predicts the test data, returning the final precision. Thanks to this, even if we select parameters experimentally, we can deduce their further modification in order to improve the network. </span></span><span class="EOP SCXW267551755 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559731&quot;:708,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p><span class="TextRun SCXW89439901 BCX0" lang="EN-GB" xml:lang="EN-GB" data-contrast="auto"><span class="NormalTextRun SCXW89439901 BCX0">The created dataset and selected parameters (learning rate = 0.00001, batch size = 32, epochs = 100) allowed to obtain the final accuracy – 97%. Considering that the image’s collection was relatively small, good results were achieved. At the end of this article, let’s show the effects of the implemented date detector on sample images of transport documents. </span></span><span class="EOP SCXW89439901 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559731&quot;:708,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<p>&nbsp;</p>
<p><img loading="lazy" decoding="async" data-attachment-id="2988" data-permalink="https://inero-software.com/few-tips-on-how-to-create-custom-class-detection-system-using-r-cnn/2_2_after-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2020/09/2_2_after-1.png" data-orig-size="946,439" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2_2_after" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2020/09/2_2_after-1-300x139.png" data-large-file="https://inero-software.com/wp-content/uploads/2020/09/2_2_after-1.png" tabindex="0" role="button" class="aligncenter wp-image-2988 size-full" src="https://inero-software.com/wp-content/uploads/2020/09/2_2_after-1.png" alt="parameters in data set" width="946" height="439" srcset="https://inero-software.com/wp-content/uploads/2020/09/2_2_after-1.png 946w, https://inero-software.com/wp-content/uploads/2020/09/2_2_after-1-300x139.png 300w, https://inero-software.com/wp-content/uploads/2020/09/2_2_after-1-768x356.png 768w, https://inero-software.com/wp-content/uploads/2020/09/2_2_after-1-646x300.png 646w" sizes="(max-width: 946px) 100vw, 946px" /></p>
<p><span data-contrast="auto">You can see in the pictures that the detecor is doing very effectively. If we would like to expand the developed detector, we would have to:</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>
<ul>
<li data-leveltext="" data-font="Symbol" data-listid="10" aria-setsize="-1" data-aria-posinset="1" data-aria-level="1"><span data-contrast="auto">prepare an extensive set of data, various date cases and their location on the document,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="10" aria-setsize="-1" data-aria-posinset="2" data-aria-level="1"><span data-contrast="auto">train the neural network again,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335551550&quot;:6,&quot;335551620&quot;:6,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="10" aria-setsize="-1" data-aria-posinset="3" data-aria-level="1"><span data-contrast="auto">depending on the metrics used, modify the parameters of the learning process,</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
<li data-leveltext="" data-font="Symbol" data-listid="10" aria-setsize="-1" data-aria-posinset="4" data-aria-level="1"><span data-contrast="auto">perform a detection on test images.</span><span data-ccp-props="{&quot;134233279&quot;:true,&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></li>
</ul>
<p><span data-contrast="auto">By following a few steps outlined in this article, You can create Your own solution by classifying a variety of objects. You can even upgrade your detector by adding more recognition classes. </span></p>
<p>&nbsp;</p>
<p><a href="https://inero-software.com/contact-us/"><strong><span style="color: #800080;">Inero Software</span></strong></a> provides knowledge and expertise on how to successfully use cutting edge technologies and data to shape corporate digital products of the future.</p>
<p><span data-contrast="auto">In the <a href="https://inero-software.com/category/blog/company/"><strong><span style="color: #800080;">blog post</span></strong></a> section you will find other articles about IT systems and more!</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="2770" data-permalink="https://inero-software.com/data-the-playground-of-machine-learning/inero-glify-10-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-orig-size="208,208" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Inero Software" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" data-large-file="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png" tabindex="0" role="button" class="aligncenter wp-image-2770 size-thumbnail" src="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png" alt="Separating icon" width="80" height="80" srcset="https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-80x80.png 80w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10-50x50.png 50w, https://inero-software.com/wp-content/uploads/2019/05/inero-glify-10.png 208w" sizes="(max-width: 80px) 100vw, 80px" /></p>
<p>Artykuł <a href="https://inero-software.com/few-tips-on-how-to-create-custom-class-detection-system-using-r-cnn/">Few tips on how to create custom class detection system using R-CNN</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2973</post-id>	</item>
	</channel>
</rss>
