How to setLanguageHint in Google OCR SDK? - ocr

I am testing few sample code for OCR using Google Cloud Vision API. I observed the APIs can able to detect English language very easily from an Image but in other language like Hindi, the APIs are not able to detect.
MyCode :
public static void detectText(String filePath) throws Exception, IOException {
System.out.println("Detect Text\n");
List<AnnotateImageRequest> requests = new ArrayList<>();
ByteString imgBytes = ByteString.readFrom(new FileInputStream(filePath));
Image img = Image.newBuilder().setContent(imgBytes).build();
Feature feat = Feature.newBuilder().setType(Feature.Type.TEXT_DETECTION).build();
AnnotateImageRequest request = AnnotateImageRequest.newBuilder().addFeatures(feat).setImage(img).build();
requests.add(request);
Credentials myCredentials = ServiceAccountCredentials.fromStream(
new FileInputStream(jsonPath));
ImageAnnotatorSettings imageAnnotatorSettings =
ImageAnnotatorSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(myCredentials))
.build();
try (ImageAnnotatorClient client = ImageAnnotatorClient.create(imageAnnotatorSettings)) {
BatchAnnotateImagesResponse response = client.batchAnnotateImages(requests);
List<AnnotateImageResponse> responses = response.getResponsesList();
for (AnnotateImageResponse res : responses) {
if (res.hasError()) {
System.out.printf("Error: %s\n", res.getError().getMessage());
return;
}
// For full list of available annotations, see http://g.co/cloud/vision/docs
for (EntityAnnotation annotation : res.getTextAnnotationsList()) {
System.out.printf("Text: %s\n", annotation.getDescription());
}
}
}
}
Image :
But the same image, i have tried in Google Drive, all the text from the image is easily detected.
Please let me know, same image how can i use in the code to detect the text?

Use ImageContext class
ImageContext imageContext = ImageContext.newBuilder()
.addLanguageHints("hi")
.build();
and set ImageContext in your AnnotateImageRequest
AnnotateImageRequest request =
AnnotateImageRequest.newBuilder()
.addFeatures(feat)
.setImage(img)
.setImageContext(imageContext)
.build();
Ref : OCR Language Support
Hope this help!

Note: I'm not a Java developer.
Below is the general representation, that matches your need in Python
{
"requests": [
{
"imageContext": {
"languageHints": [
"hi"
]
},
"features": [
{
"type": "TEXT_DETECTION"
}
]
}
]
}
Refer to: https://cloud.google.com/vision/docs/reference/rest/v1/images/annotate#ImageContext

Related

Error while linking Cloud Revit file using ExternalResourceReference - The ExternalResourceReference is not in a format that's supported by its server

I would like to link a cloud model into another Revit Model for Revit 2021 and below. After lots of exploration, one of my colleague was able to use ExternalResourceReference to successfully link the model for one of the project in Revit 2020(below is the code). But when I try to use the same code in a Revit 2021 project I'm receiving the following error:
The ExternalResourceReference (resourceReference) is not in a format that is supported by its server
var linkCloudPath = doc.GetCloudModelPath(); // the cloudpath of a BIM360 model
Guid linkedmodelguid = linkCloudPath.GetModelGUID();
Guid linkedprojectguid = linkCloudPath.GetProjectGUID();
Dictionary<string, string> Dictionary_ExternalResource = new Dictionary<string, string>(){
{"LinkedModelModelId", modelGuid.ToString()},
{"LinkedModelProjectId", projGuid.ToString()}
};
Dictionary<string, Guid> servers = new Dictionary<string, Guid>();
foreach (var service in ExternalServiceRegistry.GetServices())
{
if (service.Name == "External Resource Service")
{
IList<Guid> server_ids = service.GetRegisteredServerIds();
foreach (var server_id in server_ids)
{
servers.Add(service.GetServer(server_id).GetName(), server_id);
}
}
}
Guid BIM360ServerID = servers["BIM 360"];
ExternalResourceReference ERS = new ExternalResourceReference(BIM360ServerID, Dictionary_ExternalResource, "", "");
RevitLinkOptions options = new RevitLinkOptions(false);
LinkLoadResult result = RevitLinkType.Create(gcdoc, ERS, options); // error in this line
RevitLinkInstance.Create(gcdoc, result.ElementId);
There is no change in the code anywhere between 2020 & 2021.
I recommend to check ExternalResourceReference by calling RevitLinkType.GetExternalResourceReferences() from the link type, which has been set to BIM 360 model, so that you can get all information required.
With my testing, the below format was returned. ServerId can be used from getting ExternalServiceRegistry.GetServices() int the same manner you have tried.
{
"ServerId": "XXXXX",
"ReferenceInformation": {
"ForgeDmItemUrn": "urn:adsk.wipprod:dm.lineage:XXXXX",
"ForgeDmProjectId": "b.XXXXX",
"LinkedModelModelId": "XXXXX",
"LinkedModelProjectId": "XXXXX",
"LinkedModelRegion": "US"
},
"Version": "",
"InSessionPath": "BIM 360://XXXXX"
}
Please note that there may have been some special-casing for cloud links.
Turns out that I just needed to add region the dictionary Dictionary_ExternalResource
Dictionary<string, string> Dictionary_ExternalResource = new Dictionary<string, string>(){
{"LinkedModelRegion","US" }, // added this line
{"LinkedModelModelId", modelGuid},
{"LinkedModelProjectId", projGuid}
};

Net core dapper and postgres jsonb column

I want to POST some custom JSON to my postgres jsonb column via postman using the below request.
The custom part is sent in the "Settings" > "data" node. I don't want to apply the custom part to a model I just want to send in any kind of json and store it.
{
"name": "Test",
"settings": {
"data": {
"customdata": "hello",
"custommore": "bye"
}
}
}
The "data" node is modelled - like this:
public string Data { get; set; } //I have tried JSONDocument and Jsonb types to no avail.
Postman errors with this:
"errors": {
"$.settings.data": [
"The JSON value could not be converted to System.String. Path: $.settings.data | LineNumber: 3 | BytePositionInLine: 17."
]
}
The request doesn't even hit my controller method. I think it is because the customdata and custommore is not mapped to a model.
Is there a way of sending in custom JSON data that is not fixed to a model of any kind - or must it be part of a model?
I'm struggling to find anything about this that doesn't relate to EF core which is not what I am using.
You can use custom model binding,and get json data from HttpContext.Request.Body,and then use sonConvert.DeserializeObject to get json object.You can set the data to the format you want.
Here is a demo:
DataBinder:
public class DataBinder:IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
{
throw new ArgumentNullException(nameof(bindingContext));
}
var model1 = new Customer();
using (var reader = new StreamReader(bindingContext.HttpContext.Request.Body))
{
var body = reader.ReadToEndAsync();
var mydata = JsonConvert.DeserializeObject<JObject>(body.Result);
model1.Name = mydata["name"].ToString();
model1.Settings = new Settings
{
Data = mydata["settings"]["data"].ToString()
};
}
bindingContext.Result = ModelBindingResult.Success(model1);
return Task.CompletedTask;
}
}
Controller:
public IActionResult TestCustomModelBinding([ModelBinder(BinderType = typeof(DataBinder))]Customer customer) {
return Ok();
}
result:

flutter internationalization using dynamic string in json file

So far I was using dynamic strings as shown in the solution of this post:
Flutter internationalization - Dynamic strings
Here's an example:
AppLocalizations.of(context).userAge(18)
And on AppLocalizations.dart:
userAge(age) => Intl.message(
"My age is $age",
name: "userAge",
args: [age]);
// Return "My age is 18"
But then I read this article about flutter internationalization: https://medium.com/flutter-community/flutter-internationalization-the-easy-way-using-provider-and-json-c47caa4212b2
Which shows how to localize using json files as resource files for the strings. It looks way more convenient so I prefer to use this method, but don't know how to get strings from json file with dynamic values.
Any solution?
To get the string with the dynamic value from JSON file you can use
final age = 18 //user input.
final ageString = 'user_age'
.localisedString()
.replaceAll(new RegExp(r'\${age}'), age)
en.json
{
"user_age": "My age is ${age}",
"user_name_age": "My name is ${name} and age is ${age}"
}
string_extension.dart
extension Localisation on String {
String localisedString() {
return stringBy(this) ?? '';
}
}
Also, you could do something like,
String localisedString(Map<String, String> args) {
String str = localisedString();
args.forEach((key, value) {
str = str.replaceAll(new RegExp(r'\${'+key+'}'), value);
});
return str;
}
//usecase
final userName = 'Spider Man'
final age = '18'
final nameAgeString = 'user_name_age'.localisedString({'name': userName, 'age': age})
app_localisation.dart
Map<String, dynamic> _language;
String stringBy(String key) => _language[key] as String ?? 'null';
class AppLocalisationDelegate extends LocalizationsDelegate {
const AppLocalisationDelegate();
// override the following method if you want to specify the locale you are supporting.
final _supportedLocale = ['en'];
#override
bool isSupported(Locale locale) => _supportedLocale.contains(locale.languageCode);
#override
Future load(Locale locale) async {
String jsonString = await rootBundle
.loadString("assets/strings/${locale.languageCode}.json");
_language = jsonDecode(jsonString) as Map<String, dynamic>;
print(_language.toString());
return SynchronousFuture<AppLocalisationDelegate>(
AppLocalisationDelegate());
}
#override
bool shouldReload(AppLocalisationDelegate old) => false;
}
Create a folder say json in your assets directory. Put your language files in it.
assets
json
- en.json // for English
- ru.json // for Russian
Now in en.json, write your string, for example.
{
"myAge": "My age is"
}
Similarly, in ru.json,
{
"myAge": "Мой возраст"
}
Add this to the pubspec.yaml file (mind the spaces)
flutter:
uses-material-design: true
assets:
- assets/json/
Run flutter pub get
Initial work done. Let's move to the code side.
Copy this boilerplate code in your file:
Map<String, dynamic> language;
class AppLocalizations {
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
String getText(String key) => language[key];
String userAge(int age) => '${getText('myAge')} $age';
}
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const AppLocalizationsDelegate();
#override
bool isSupported(Locale locale) => ['en', 'ru'].contains(locale.languageCode);
#override
Future<AppLocalizations> load(Locale locale) async {
final string = await rootBundle.loadString('assets/json/${locale.languageCode}.json');
language = json.decode(string);
return SynchronousFuture<AppLocalizations>(AppLocalizations());
}
#override
bool shouldReload(AppLocalizationsDelegate old) => false;
}
Set up few things in MaterialApp widget:
void main() {
runApp(
MaterialApp(
locale: Locale('ru'), // switch between "en" and "ru" to see effect
localizationsDelegates: [const AppLocalizationsDelegate()],
supportedLocales: [const Locale('en'), const Locale('ru')],
home: HomePage(),
),
);
}
Now, you can simply use above delegate:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
var age = AppLocalizations.of(context).userAge(18);
// prints "My age is 18" for 'en' and "Мой возраст 18" for 'ru' locale.
print(age);
return Scaffold();
}
}
I've tried various solutions to implement localization, and the best I've come across is the Flutter Intl plugin for VS Code or Android Studio/IntelliJ made by Localizely.com (not affiliated).
With it, basically you install the plugin using the marketplace/plugin library, then initialize for your project using the menu option. This creates a default english locale in lib/l10n/intl_en.arb (which sounds scary but is actually just JSON) and sets up all the scaffolding for the internationalization in lib/generated.
You also have to add the following to your dependencies.
flutter_localizations:
sdk: flutter
You can then add keys to this file and they'll be automatically available in your app, by importing generated/l10n.dart which contains a class called S.
To get flutter to use it, wherever it is that you initialize your MaterialApp, make sure to pass S.delegate into MaterialApp's localizationsDelegates parameter (most likely as part of an array with GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, and possibly GlobalCupertinoLocalizations.delegate.) You also have to add S.delegate.supportedLocales to MaterialApp's supportedLocales.
To add more locales, use the option in the menu (in intellij at least) or simply create more intl_.arb files, and the plugin will automatically recognize this and set up the relevant code.
Say you have an intl_en file with the following:
{ "name": "Name" }
You'd then use S.of(context).name to use the string in your code.
All this is more eloquently explained on localizely's website.
Now, to use keys in these .arb files, you simply have to wrap it in {...}. So for example:
{ "choose1OfNumOptions": "Choose 1 of {numoptions} options" }
would lead to a usage of S.of(context).choose1OfNumOptions(numOptions);. I don't know that the plugin supports the full ARB specification but it does support at least the basics.
Also, I'm not using Localizely but it seems like it'd be a pretty useful way to manage the translations and the plugin integrates automatically, although I think it's also pretty horrendously overpriced - at least for my app, which happens to have a ton of text. I actually just have a google sheet where I store all my translations, and when it's time to update it I download it as a .tsv and wrote a simple little parser to write out to the .arb files.
flutter_localizations:
app_en.arb:
{
"contactDetailsPopupEmailCopiedMessage": "Copied {email} to clipboard",
"#contactDetailsPopupEmailCopiedMessage": {
"description": "Message being displayed in a snackbar upon long-clicking email in contact details popup",
"placeholders": {
"email": {
"type": "String",
"example": "example#gmail.com"
}
}
}
}
app_localizations.dart:
abstract class AppLocalizations {
/// Message being displayed in a snackbar upon long-clicking email in contact details popup
///
/// In en, this message translates to:
/// **'Copied {email} to clipboard'**
String contactDetailsPopupEmailCopiedMessage(String email);
}
usage:
l10n.contactDetailsPopupEmailCopiedMessage("example#gmail.com")
For more details take a look here.

JSON ignore fields outside data maps

I am getting some response :
var xxx_api = { "user" : {
"name":"satishpandey",
"sites":[
{
"name":"SEO Product",
"url":"http://www.xxx.com/"
} ]
}};
I want to exclude all the string those are outside json data.
var xxx_api and ; are needs to be excluded.
Is there anything in jackson to exclude these strings?
Assuming you are using this in a get/post (restful-like) method, maybe that has to do with the header of the webservice method you are using. I am using REST and I am able to specify the format I want to receive the json input like this
#POST
#Path("/post")
#Consumes(MediaType.APPLICATION_JSON)
public Response myMethod(#FormParam("post") String jsonInput){
// ...
// use jsonInput
mapper.readValue(jsonInput, ...);
// ...
}
Considering this, I guess the input written to the var jsonInput (in the header) would be
{ "user" : {
"name":"satishpandey",
"sites":[
{
"name":"SEO Product",
"url":"http://www.xxx.com/"
} ]
}};
I didn't find any solutions for it in jackson. Now I am using String.substring() method for getting the desired results.
StringBuilder stringBuilder = new StringBuilder(jsonString);
stringBuilder.replace(0, stringBuilder.indexOf("{"), "");
stringBuilder.replace(stringBuilder.lastIndexOf("}") + 1, stringBuilder.length(), "");
It is working perfectly for me.

Bitly, Json, and C#

I'm working on something that involved using the Bit.ly API, and allow the user to select theformat (Text, XML, Json) the text & XML are completed. This is the Json result that is returned when you shorten a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"url": "http:\/\/rlm.cc\/gtYUEd",
"hash": "gtYUEd",
"global_hash": "evz3Za",
"new_hash": 0
}
}
And this C# code works just fine to parse it and get the short URL:
var serializer2 = new JavaScriptSerializer();
var values2 = serializer2.Deserialize<IDictionary<string, object>>(json);
var results2 = values2["data"] as IDictionary<string, object>;
var shortUrl2 = results2["url"];
expandedUrl = results2["url"].ToString();
return results2["url"].ToString();
Now here's the Json sent back when expanding a URL:
{
"status_code": 200,
"status_txt": "OK",
"data":
{
"expand":
[
{
"short_url": "http:\/\/rlm.cc\/gtYUEd",
"long_url": "http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}",
"user_hash": "gtYUEd",
"global_hash": "evz3Za"
}
]
}
}
Ad that's where my problem begins, how can I change my current C# to be able to handle both scenarios, because as you can see their vastly different from each other. Any ideas?
I usually use Json.NET to cherrypick values out of JSON documents. The syntax is very concise. If you reference NewtonSoft.Json.dll and use Newtonsoft.Json.Linq, you can write the following:
var job = JObject.Parse(jsonString);
if (job["data"]["expand"] == null)
{
Console.WriteLine((string)job["data"]["url"]);
}
else
{
Console.WriteLine((string)job["data"]["expand"][0]["long_url"]);
}
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": {""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""url"": ""http:\/\/rlm.cc\/gtYUEd"", ""hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"", ""new_hash"": 0 }}";
the routine will display http://rlm.cc/gtYUEd.
If jsonString is:
string jsonString = #"{""status_code"": 200, ""status_txt"": ""OK"", ""data"": { ""expand"": [ { ""short_url"": ""http:\/\/rlm.cc\/gtYUEd"", ""long_url"": ""http:\/\/panel.aspnix.com\/Default.aspx?pid={Removed}"", ""user_hash"": ""gtYUEd"", ""global_hash"": ""evz3Za"" } ] } }";
the routine will display http://panel.aspnix.com/Default.aspx?pid={Removed}.
Not sure I got your problem. Why aren't you testing, if you got a shortening result or a expanding result? Since they are different, this could easily be done via simple 'if ()' statements:
if (results2.ContainsKey("expand")) {
// handle the expand part
} else {
// handle the shorten part
}
Assuming that the provider is consistent with which form it sends, do you need to have code that handles both? It should be direct to handle each individually.
If you can't know ahead of time which format you will get back, you can do the following:
if (results2.ContainsKey("expand"))
{
//Second example
}
else
{
//First example
}