LoginSignup
1
2

More than 3 years have passed since last update.

asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_8.分割処理 Google Books API-

Posted at

棚画像を分割する方法について(Qiita説明用)

Qiitaでこれを全部説明したところでニーズもないので、掻い摘んでの説明になります!
1.本の文字部分をマウスで選択
2.Enterで本の画像を送信
-ここから非同期-
3.画像を分割
4.OCR処理
5.取得した文字を本検索
-ここまで非同期-
6.画面に結果表示

今回は、「5.取得した文字を本検索」です。
Google Books APIでの利用となります。

Google Books APIの参考サイト

最初のきっかけはこのサイト

書籍検索APIはGoogleBooksAPIsがオススメ【導入も楽ちんです】:
 https://manablog.org/google-books-apis/

このサイトを見て導入を決め、もろもろ調べ、Google公式マニュアルを参考に実装しました。

送受信するデータについて

他のサイトで山ほど情報があるので、説明する必要がないのですが、一応。。。
URLにパラメータを追加するだけで検索が行える!が他サイトの説明が多数となっておりますが、
検索結果の表示画面で、ページング処理も行いたいので、他のパラメータも追加して検索を実施します。

そして、Jsonフォーマットで返却されますが、C#上でどのように処理をするのか。という点では、
ニーズがあるかも。

受信データ(JSON)のクラス化

さて、まずはクラスにしてしまいましょう。
これはご存知かと思いますが、JSONをC#の構造体クラスに変換してくれるサービスがあります。

各種API連携する場合には、必須のWebツールだと考えております。

json2csharp:
 http://json2csharp.com/

ということで、まずはベースとなるJSONデータを検索します。

https://www.googleapis.com/books/v1/volumes?q=生命と環境の化学
image.png

このJSONを、json2csharpへコピペ!

image.png

↓ Generate ↓

image.png

↓ Copy ↓

新しいクラスを作成して、貼り付け!

image.png

Models\GoogleBooks\GoogleBooks.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace sample2_1.Models.GoogleBooks
{
    public class GoogleBooks
    {

        public class IndustryIdentifier
        {
            public string type { get; set; }
            public string identifier { get; set; }
        }

        public class ReadingModes
        {
            public bool text { get; set; }
            public bool image { get; set; }
        }

        public class ImageLinks
        {
            public string smallThumbnail { get; set; }
            public string thumbnail { get; set; }
        }

        public class PanelizationSummary
        {
            public bool containsEpubBubbles { get; set; }
            public bool containsImageBubbles { get; set; }
        }

        public class VolumeInfo
        {
            public string title { get; set; }
            public List<string> authors { get; set; }
            public string publishedDate { get; set; }
            public string description { get; set; }
            public List<IndustryIdentifier> industryIdentifiers { get; set; }
            public ReadingModes readingModes { get; set; }
            public int pageCount { get; set; }
            public string printType { get; set; }
            public string maturityRating { get; set; }
            public bool allowAnonLogging { get; set; }
            public string contentVersion { get; set; }
            public ImageLinks imageLinks { get; set; }
            public string language { get; set; }
            public string previewLink { get; set; }
            public string infoLink { get; set; }
            public string canonicalVolumeLink { get; set; }
            public string subtitle { get; set; }
            public string publisher { get; set; }
            public List<string> categories { get; set; }
            public PanelizationSummary panelizationSummary { get; set; }
        }

        public class ListPrice
        {
            public double amount { get; set; }
            public string currencyCode { get; set; }
        }

        public class RetailPrice
        {
            public double amount { get; set; }
            public string currencyCode { get; set; }
        }

        public class ListPrice2
        {
            public double amountInMicros { get; set; }
            public string currencyCode { get; set; }
        }

        public class RetailPrice2
        {
            public double amountInMicros { get; set; }
            public string currencyCode { get; set; }
        }

        public class Offer
        {
            public int finskyOfferType { get; set; }
            public ListPrice2 listPrice { get; set; }
            public RetailPrice2 retailPrice { get; set; }
        }

        public class SaleInfo
        {
            public string country { get; set; }
            public string saleability { get; set; }
            public bool isEbook { get; set; }
            public ListPrice listPrice { get; set; }
            public RetailPrice retailPrice { get; set; }
            public string buyLink { get; set; }
            public List<Offer> offers { get; set; }
        }

        public class Epub
        {
            public bool isAvailable { get; set; }
            public string acsTokenLink { get; set; }
        }

        public class Pdf
        {
            public bool isAvailable { get; set; }
            public string acsTokenLink { get; set; }
        }

        public class AccessInfo
        {
            public string country { get; set; }
            public string viewability { get; set; }
            public bool embeddable { get; set; }
            public bool publicDomain { get; set; }
            public string textToSpeechPermission { get; set; }
            public Epub epub { get; set; }
            public Pdf pdf { get; set; }
            public string webReaderLink { get; set; }
            public string accessViewStatus { get; set; }
            public bool quoteSharingAllowed { get; set; }
        }

        public class SearchInfo
        {
            public string textSnippet { get; set; }
        }

        public class Item
        {
            public string kind { get; set; }
            public string id { get; set; }
            public string etag { get; set; }
            public string selfLink { get; set; }
            public VolumeInfo volumeInfo { get; set; }
            public SaleInfo saleInfo { get; set; }
            public AccessInfo accessInfo { get; set; }
            public SearchInfo searchInfo { get; set; }
        }

        public class RootObject
        {
            public string kind { get; set; }
            public int totalItems { get; set; }
            public List<Item> items { get; set; }
        }
    }
}

これで、受信データ(JSON)を変換することで、オブジェクトとして扱うことが出来ます。

送信データ処理

こちらも、別クラスを作って処理を行います。

Models\GoogleBooks\GoogleBooksApi.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Runtime.Serialization.Json;
using System.Threading.Tasks;

namespace sample2_1.Models.GoogleBooks
{
    public class GoogleBooksApi
    {
        public static async Task<GoogleBooks.RootObject> GetGoogleBooks(string s_word)
        {
            // 返却用オブジェクト
            GoogleBooks.RootObject rootObject = new GoogleBooks.RootObject();

            using (HttpClient client = new HttpClient())
            {
                var parameters = new Dictionary<string, string>()
                {
                    { "q", s_word },
                    { "Country", "JP" },
                    { "maxResults", "30" }
                };
                // パラメータつけてGET
                HttpResponseMessage response = await client.GetAsync($"https://www.googleapis.com/books/v1/volumes?{await new FormUrlEncodedContent(parameters).ReadAsStringAsync()}");
                response.EnsureSuccessStatusCode();
                // 返却値をJSONからクラスへ変換
                var serializer = new DataContractJsonSerializer(typeof(GoogleBooks.RootObject));
                rootObject = (GoogleBooks.RootObject)serializer.ReadObject(await response.Content.ReadAsStreamAsync());
            }
            // 出来たオブジェクトを変換
            return rootObject;
        }
    }
}

Controllerへ実装

上記で作ったメソッドを呼び出すだけですね。
簡単簡単。

Controllers\WorkController.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Drawing;
using Amazon;
using Amazon.S3;
using Amazon.S3.Transfer;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

using sample2_1.Models;
using sample2_1.Models.Const;
using sample2_1.Models.Interface;
using sample2_1.Models.GoogleVision;
using sample2_1.Models.GoogleBooks;

namespace sample2_1.Controllers
{
    public class WorkController : Controller
    {
        // AmazonS3 インターフェイス
        private static IAmazonS3 client;

        public IActionResult Index()
        {
            --
        }

        [HttpPost("UploadFiles")]
        public async Task<IActionResult> FileUpload(List<IFormFile> files)
        {
            --
        }

        // S3 ストレージへアップロード!
        static async Task WritingAnObjectAsync(string s_upd_file_nm)
        {
            --
        }

        //asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_6.分割画面→Canvasオブジェクト- 追加
        public IActionResult Canvas()
        {
            --
        }


        [HttpPost]
        //FormからJsonを受け取り、クラス変換してくれます。
        public string Cut([FromBody]CutData cutData)
        {
            // 1.Imageへ画面に表示している画像ファイルを読み込み
            System.Drawing.Image image = null;
            try
            {
                image = System.Drawing.Image.FromFile(@"C:\work\work.jpg");
            }
            catch (Exception e)
            {
                throw e;
            }

            // 2.Bitmapに範囲指定したサイズを設定
            Bitmap destbmp = new Bitmap((int)cutData.width, (int)cutData.height);
            // 3.Graphicsに読み込ませるBitmapを設定
            Graphics graphics = Graphics.FromImage(destbmp);
            // 4.[1]でロードした画像を描画
            graphics.DrawImage(image, (cutData.x * -1) , (cutData.y * -1), image.Size.Width, image.Size.Height);
            // 5.保存先の指定
            var stream = new FileStream(@"C:\work\cutter.jpg", FileMode.Create);
            // 6.保存処理
            destbmp.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
            // 7.後処理
            stream.Close();

            // 8.Google Vision API 認証準備
            GCPVisonAPI ocr = new GCPVisonAPI();
            // 9.戻り値stringの変数作成、画像をByteArrayで開く
            string getText = "";
            byte[] imageArray = System.IO.File.ReadAllBytes(@"C:\work\cutter.jpg");
            // 10.Google Vision APIの実行
            ocr.getTextAndRoi(imageArray, ref getText);


            // 11.Google Books APIのパラメータ作成
            GoogleBooks.RootObject rootObject = GoogleBooksApi.GetGoogleBooks(getText).Result;
            // 12.検索結果の書籍名+著者名を返却する
            string s_res = "";
            foreach (var item in rootObject.items)
            {
                // タイトルの取得
                s_res = item.volumeInfo.title;
                s_res += " / ";

                // 作者名を取得
                var cnt = 0;
                foreach (string s_author in item.volumeInfo.authors)
                {
                    if (cnt != 0)
                    {
                        s_res += ",";
                    }
                    s_res += s_author;
                    cnt++;
                }
                // 1件目で終了!
                break;
            }

            // 検索結果の書籍名+著者名を返却する
            return s_res;

            // 受けとった文字列を返却
            //return getText;

            // 受け取ったheightプロパティを画面に返す。
            //return @"正常にCut出来ました!";
        }
    }
}

デバッグ実行!

前回同様、「生命と環境の化学」を選択して、Enter!ターンッ!
image.png

↓ 結果 ↓

image.png

「基礎から学ぶ生命・環境の化学 / 三浦洋四郎,船越浩海,岡崎三代」

ん?合ってるの?

GoogleBooksで実際に見てみましょう。

image.png

一応合ってるっぽい!良かった!

最後に

これで、一通り実装は完了です。
簡単なアプリケーションなら作れそうな気がしませんか?
是非、色々遊んでみてください。

開発編は一旦ここまで。
ネタはあるのですが、ありきたりな話なので、また時間がある時に・・・。
ちなみにこんな感じを想定

asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_9.分割処理 DB登録-
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_10.本一覧画面 DB検索-
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_11.本一覧画面 ページング-
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_12.本詳細画面-
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_13.本修正画面→Google Books API検索-

ページングはそこそこ苦労しました。
未だに0件対応ちゃんとやってないし。。。

これからTanaToruの改修をもろもろやりきったら、また更新します。
次の予定は、サーバデプロイ編。
乞うご期待。


【是非お試しください】※完全無料です
TanaToru -本棚管理サービス-
 https://app.zero-one-system.co.jp/TanaToru/

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2