花、ハエ、よく練習されたランダムな機械学習

前のシリーズでは、ハエから合理的な生き物を作ろうとしました。 簡単に-動作しませんでした。 ハエは頑固に学びたくありませんでした。







ハエは、行列乗算、シグモイド、誤差の逆伝播に基づく小さな単純なニューラルネットワークでした。 彼女の教えは花のある写真の認識でした。



内部に2つのネットワークがあることを思い出させてください。最初のネットワークは元の画像の断片を分析し、2番目のネットワークは最初のグリッドの結果で構成されるマトリックスを処理します。



何とかしてトレーニングが行われたが、結果はなかった。 その後、有効な理由(土曜日の夕方、日曜日の夜、朝など)でトレーニングの試みを放棄し、次に何をすべきかを考えました。 可能な解決策の一部は、最初の記事の最後に概説されており、引き続き継続されました。



オプション1.別の中間層



ニューロンをハエに追加すると、ハエが少し賢くなると想定されていました。 レイヤーの追加は簡単です-代わりに



nn2 = NN([middleShape, (y.shape[1], middleShape[0]), y.shape])
      
      





書きます



 nn2 = NN([middleShape, (40, middleShape[0]), (y.shape[1], 40), y.shape])
      
      





レイヤーが追加され、学習と計算のプロセスが大幅に遅くなりましたが、良くはなりませんでした。 実際、結果はまったく変更されていないため、ここでは説明しません。



オプション2.成功へのアプローチを空白として使用する



アイデアは、最も成功した学習成果のシナプスの重みを記憶し、通常のようにランダムな値でハンマーするのではなく、これらの重みでネットワークを訓練することでした。



グリッドのシナプスは、それぞれ1番目と2番目のグリッドのnn.net.synsおよびnn2.syns属性の内容です。 結果は、行われたエラーの数、つまり サンプル全体で、花ではなく花の両方を含む誤って分類された写真の数。



  minFails = None lastSyns = None for epoch in range(100): nn = ImgNN(firstShape, resultShape=middleShape, imageSize=imageSize) nn2 = NN([middleShape, (y.shape[1], middleShape[0]), y.shape]) #   for f in fl: i = readImage(f, imageSize) nn.learn(i, yy, 2) mid = nn.calc(i) nn2.learn(mid, y, 1000) nextSyns=None fails = 0 failFiles = [] #    for f in all: i = readImage(f, imageSize) mid = nn.calc(i) res = nn2.calc(mid) delta = (y-res) v = round(np.std(delta),3) if v > 0.2 and f in fl: #  -    - fails += 1 failFiles.append(f) elif v<0.2 and f in nofl: #  - -    fails +=1 failFiles.append(f)
      
      





エラーが少なくなったら、グリッドの現在の状態を修正し、初期化に渡します。



  nn = ImgNN(firstShape, resultShape=middleShape, imageSize=imageSize) if not (lastSyns is None): nn.net.syns = lastSyns nn2 = NN([middleShape, (y.shape[1], middleShape[0]), y.shape]) #   #    if minFails == None or fails < minFails: minFails = fails lastSyns = nn.net.syns
      
      





確認する



最良の結果:試行25で4エラー
Epoch = 25

flowers\178.jpg res = [[ 0.64 0.89 0.65 0.87]] v = 0.619

flowers\179.jpg res = [[ 0.91 0.2 0.96 0.15]] v = 0.12

flowers\180.jpg res = [[ 0.95 0.1 0.95 0.1 ]] v = 0.074

flowers\182.jpg res = [[ 1. 0. 1. 0.]] v = 0.0

flowers\186-2.jpg res = [[ 0.98 0.05 0.98 0.04]] v = 0.032

flowers\186.jpg res = [[ 0.99 0.01 0.99 0.01]] v = 0.01

flowers\187.jpg res = [[ 0.83 0.48 0.81 0.5 ]] v = 0.335

flowers\190 (2).jpg res = [[ 1. 0. 1. 0.]] v = 0.001

flowers\190.jpg res = [[ 0.96 0.06 0.96 0.05]] v = 0.045

flowers\191.jpg res = [[ 0.97 0.01 0.96 0.01]] v = 0.022

flowers\195.jpg res = [[ 1. 0. 1. 0.]] v = 0.004

flowers\199.jpg res = [[ 0.91 0.16 0.9 0.16]] v = 0.127

flowers\2.jpg res = [[ 0.99 0.01 0.99 0.01]] v = 0.009

flowers\200.jpg res = [[ 0.99 0.01 1. 0.01]] v = 0.009

noflowers\032.jpg res = [[ 0.71 0.73 0.79 0.73]] v = 0.49

noflowers\085.jpg res = [[ 0.87 0.29 0.85 0.32]] v = 0.222

noflowers\088.jpg res = [[ 0.92 0.22 0.94 0.24]] v = 0.15

noflowers\122.JPG res = [[ 0.72 0.68 0.73 0.68]] v = 0.479

noflowers\123.jpg res = [[ 0.74 0.54 0.69 0.6 ]] v = 0.427

noflowers\173.jpg res = [[ 0.43 0.9 0.57 0.9 ]] v = 0.702

noflowers\202.jpg res = [[ 0.99 0. 0.98 0. ]] v = 0.008

noflowers\205.jpg res = [[ 0.34 0.92 0.57 0.81]] v = 0.711

noflowers\cutxml.jpg res = [[ 0.79 0.41 0.79 0.41]] v = 0.309

noflowers\Getaway.jpg res = [[ 0.75 0.65 0.76 0.65]] v = 0.449

noflowers\IMGP1800.JPG res = [[ 0.81 0.55 0.81 0.55]] v = 0.367

noflowers\trq-4.png res = [[ 0.52 0.81 0.54 0.83]] v = 0.644

dy = 1.407 dn = 4.958

fails = 4 ['flowers\\178.jpg', 'flowers\\187.jpg', 'noflowers\\088.jpg', 'noflowers\\202.jpg']

min = 4








ネットワークは再び何も学習しませんでした。 なんてバカなフライだ!



実際、ネットワークはまだ何かを学びましたが。 拒否された写真を見ると、花に割り当てられたネットワークが、黄色い葉が散らばったbeatられた赤い車であることがわかります。 想像力があれば、それは本当に花と間違われる可能性があります。











オプション3。そして彼らはそこであなたに教えているのは何ですか?



次の影響ポイントは、最初のネットワークのトレーニングの目標でした。 実際には、2番目のネットワークの入力で蓄積されたエラーは、最初のネットワークの出力を介して送信することはできません。 さて、どのように送信しないか...あなたは転送することができますが、それはまだプログラムする必要があります。 そして、私は怠けすぎて、最初のネットワークを単一のマトリックスでトレーニングし始めました。



  yy = np.zeros(middleShape) np.fill_diagonal(yy,1)
      
      





\ begin {bmatrix}

1&0&\ cdots&0 \\

0&1&\ cdots&0 \\

\ cdots&\ cdots&\ cdots&\ cdots \\

0&0&\ cdots&1

\ end {bmatrix}

どうやら人工的に見え、明らかに学習を妨げます。 しかし、結果マトリックスはどうあるべきか、私は知りませんでした。 シナプスをコピーするゲームは、ターゲットの学習マトリックスを持つといいと思いました yy また、成功した試行からコピーするため、徐々に最良の結果に近づきます。



しかし、問題がありました-私は1つのサンプルを持っていませんでした。 最初のネットワークを単一のマトリックスでトレーニングし、入力にさまざまな画像を与えます。 それらのそれぞれについて、出力で値の特定のマトリックスを提供します。 どの結果のマトリックスをサンプルとして使用する必要がありますか?



「本物のヒーローは常に回っている」ことを知って、私は単にこれをしませんでしたが、サンプルのために同じ単一のマトリックスを取りました。 しかし、彼はそれに小さな小さなエラーを追加しただけです。 そして、サイクルが成功した場合、すなわち エラーの次の最小値に達した場合、最後のサンプルが次のターゲット結果になります。



  yy = np.zeros(middleShape) np.fill_diagonal(yy,1) minFails = None lastYY = yy nextYY = yy ... for epoch in range(100): ... for f in fl: i = readImage(f, imageSize) nn.learn(i, nextYY, 2) mid = nn.calc(i) nn2.learn(mid, y, 1000) ... for f in all: i = readImage(f, imageSize) mid = nn.calc(i) res = nn2.calc(mid) ... if minFails == None or fails < minFails: minFails = fails lastYY = nextYY else: nextYY = lastYY +(np.random.random(yy.shape)-0.5)/10
      
      







おそらく、私が数学者であれば、チャンスを学習ツールとして使用することはまずないでしょう。 数学者は、学習によって必然的に期待される結果が得られる理論を構築します。 N 移動する場合、多次元空間の曲面上で積分を計算し、それに関する微分を取るだけです。 x 。 しかし、私は数学者ではなく、どこかに解決策があり、近くにあるという非数学的な期待にのみ頼ることができます。



最良の結果:4回の試行でエラー79
Epoch = 79

flowers\178.jpg res = [[ 0.5 0.13 0.52 0.12]] v = 0.309

flowers\179.jpg res = [[ 0.74 0.06 0.75 0.06]] v = 0.16

flowers\180.jpg res = [[ 0.76 0.07 0.75 0.07]] v = 0.155

flowers\182.jpg res = [[ 0.95 0.03 0.94 0.03]] v = 0.044

flowers\186-2.jpg res = [[ 0.7 0.1 0.71 0.09]] v = 0.193

flowers\186.jpg res = [[ 0.61 0.22 0.6 0.2 ]] v = 0.303

flowers\187.jpg res = [[ 0.45 0.13 0.45 0.13]] v = 0.341

flowers\190 (2).jpg res = [[ 0.84 0. 0.67 0.01]] v = 0.14

flowers\190.jpg res = [[ 0.96 0.06 0.94 0.08]] v = 0.061

flowers\191.jpg res = [[ 0.73 0.13 0.72 0.1 ]] v = 0.194

flowers\195.jpg res = [[ 0.85 0.03 0.88 0.03]] v = 0.08

flowers\199.jpg res = [[ 0.83 0.05 0.84 0.04]] v = 0.102

flowers\2.jpg res = [[ 0.81 0.06 0.81 0.06]] v = 0.125

flowers\200.jpg res = [[ 0.92 0.05 0.93 0.04]] v = 0.057

noflowers\032.jpg res = [[ 0.27 0.12 0.3 0.1 ]] v = 0.416

noflowers\085.jpg res = [[ 0.41 0.14 0.41 0.14]] v = 0.365

noflowers\088.jpg res = [[ 0.37 0.15 0.32 0.15]] v = 0.402

noflowers\122.JPG res = [[ 0.4 0.15 0.4 0.14]] v = 0.373

noflowers\123.jpg res = [[ 0.35 0.14 0.33 0.15]] v = 0.401

noflowers\173.jpg res = [[ 0.33 0.17 0.34 0.17]] v = 0.418

noflowers\202.jpg res = [[ 0.44 0.14 0.45 0.12]] v = 0.342

noflowers\205.jpg res = [[ 0.63 0.06 0.74 0.07]] v = 0.192

noflowers\cutxml.jpg res = [[ 0.52 0.13 0.45 0.13]] v = 0.323

noflowers\Getaway.jpg res = [[ 0.38 0.15 0.38 0.15]] v = 0.386

noflowers\IMGP1800.JPG res = [[ 0.4 0.15 0.4 0.14]] v = 0.371

noflowers\trq-4.png res = [[ 0.19 0.21 0.17 0.28]] v = 0.533

dy = 2.264 dn = 4.522

fails = 4 ['flowers\\178.jpg', 'flowers\\186.jpg', 'flowers\\187.jpg', 'noflowers\\205.jpg']

min = 4








ここで、ネットワークは白いコネクタも花のように見えると考えました。







一般に、このコネクタはほとんどすべてのオプションで花と見なされていました。 まあ、それは理解できる、彼らは彼女ににおいを与えません。



オプション4.そして、ブランドを結合しましょう



以前のオプションはほぼ同じ結果を示しました。 この時点で、私はそれをやっているのかどうか、そして不幸なフライからやりすぎたかどうかを考える時間がありました。 しかし、そこで止まりませんでした。



次のオプションは、前の2つを同時に使用することでした-シナプスの値を記憶する試みに成功し、最初の行列をトレーニングする目的で、検索を拡張するためにランダム性を使用します。



  for epoch in range(100): print('Epoch =', epoch) nn = ImgNN(firstShape, resultShape=middleShape, imageSize=imageSize) if not (lastSyns is None): nextSyns = lastSyns for r in range(len(nextSyns)): rand = (np.random.random(nextSyns[r].shape)-0.5)/20 nextSyns[r] = nextSyns[r] + rand nn.net.syns = nextSyns nn2 = NN([middleShape, (y.shape[1], middleShape[0]), y.shape]) for f in fl: i = readImage(f, imageSize) nn.learn(i, nextYY, 2) mid = nn.calc(i) nn2.learn(mid, y, 1000) ... if minFails == None or fails < minFails: minFails = fails lastSyns = nn.net.syns lastYY = nextYY else: nextYY = lastYY +(np.random.random(yy.shape)-0.5)/20
      
      





最良の結果:2回の試行でエラー38
Epoch = 38

flowers\178.jpg res = [[ 0.91 0.26 0.91 0.25]] v = 0.174

flowers\179.jpg res = [[ 0.99 0. 0.99 0. ]] v = 0.005

flowers\180.jpg res = [[ 0.9 0.21 0.89 0.2 ]] v = 0.153

flowers\182.jpg res = [[ 1. 0. 1. 0.]] v = 0.0

flowers\186-2.jpg res = [[ 1. 0.01 0.99 0.01]] v = 0.008

flowers\186.jpg res = [[ 0.91 0.12 0.93 0.07]] v = 0.09

flowers\187.jpg res = [[ 0.83 0.43 0.83 0.44]] v = 0.303

flowers\190 (2).jpg res = [[ 1. 0. 1. 0.]] v = 0.0

flowers\190.jpg res = [[ 1. 0. 1. 0.]] v = 0.001

flowers\191.jpg res = [[ 1. 0. 1. 0.]] v = 0.0

flowers\195.jpg res = [[ 0.99 0. 1. 0. ]] v = 0.004

flowers\199.jpg res = [[ 0.97 0.03 0.98 0.03]] v = 0.029

flowers\2.jpg res = [[ 1. 0. 1. 0.]] v = 0.003

flowers\200.jpg res = [[ 1. 0. 1. 0.]] v = 0.0

noflowers\032.jpg res = [[ 0.88 0.55 0.8 0.67]] v = 0.389

noflowers\085.jpg res = [[ 0.25 0.96 0.27 0.96]] v = 0.848

noflowers\088.jpg res = [[ 0.84 0.42 0.79 0.37]] v = 0.29

noflowers\122.JPG res = [[ 0.68 0.66 0.69 0.66]] v = 0.49

noflowers\123.jpg res = [[ 0.74 0.63 0.71 0.6 ]] v = 0.445

noflowers\173.jpg res = [[ 0.86 0.46 0.76 0.52]] v = 0.343

noflowers\202.jpg res = [[ 0.22 0.92 0.44 0.95]] v = 0.808

noflowers\205.jpg res = [[ 0.8 0.82 0.71 0.88]] v = 0.547

noflowers\cutxml.jpg res = [[ 0.99 0.03 0.97 0.02]] v = 0.022

noflowers\Getaway.jpg res = [[ 0.7 0.65 0.7 0.65]] v = 0.474

noflowers\IMGP1800.JPG res = [[ 0.79 0.5 0.77 0.5 ]] v = 0.36

noflowers\trq-4.png res = [[ 0.77 0.21 0.69 0.07]] v = 0.215

dy = 0.77 dn = 5.231

fails = 2 ['flowers\\187.jpg', 'noflowers\\cutxml.jpg']

min = 2








28個のファイルで2つのエラー= 7%十分な結果であると考えましたが、改善することはできません。



最終的な写真の実行と結論



プロセスの最後に、訓練されたメッシュ、または最良の結果を得るためにシナプスの値をテキストファイルに保存しました。



  for i in range(len(lastSyns)): np.savetxt('syns_save%s.txt'%i, lastSyns[i]) for i in range(len(lastSyns2)): np.savetxt('syns2_save%s.txt'%i, lastSyns2[i])
      
      





それから彼は写真からネットワークを運転しました:



  StartLearn = False if not StartLearn: pictDir = 'C:\\AllPictures' nn = ImgNN(firstShape, resultShape=middleShape, imageSize=imageSize) nn.net.syns[0] = np.loadtxt('syns_save0.txt',ndmin=nn.net.syns[0].ndim) nn.net.syns[1] = np.loadtxt('syns_save1.txt',ndmin=nn.net.syns[1].ndim) nn2 = NN([middleShape, (y.shape[1], middleShape[0]), y.shape]) nn2.syns[0] = np.loadtxt('syns2_save0.txt',ndmin=nn2.syns[0].ndim) nn2.syns[1] = np.loadtxt('syns2_save1.txt',ndmin=nn2.syns[1].ndim) files = [e.path for e in os.scandir(pictDir)] for f in files: i = readImage(f, imageSize) mid = nn.calc(i) res = nn2.calc(mid) delta = y-res v = round(np.std(delta),3) if v <= 0.3: print('Flower',f,v) ## else: ## print('No flower',f, v)
      
      





一般に、彼女が花だけを見つけたと言うわけではありません。 猫、カニ、花火、石だけ、そして人々のグループが出会いました。 そして、私の写真の中にはほんの少しの花がありました。



原則として、ネットワークは機能し、そのためのタスクは複雑すぎたと結論付けることができます。 ImageNetを見ると、 Dark_Daiverが以前の記事のコメントでに助言したように、色はあまりにも多様であるため、このような単純なネットワークでは区別できません。



ソースコード
 import numpy as np from nnmat import * import os import sys from PyQt5.QtGui import * from PyQt5.QtCore import * import meshandler import random import cv2 class ImgNN: def __init__(self, shape, resultShape = (16, 16), imageSize = (400,400)): self.resultShape = resultShape self.w = imageSize[0] // shape[0] self.h = imageSize[1] // shape[1] self.net = NN([shape, (1,shape[0]), (1,1)]) self.shape = shape self.imageSize = imageSize def learn(self, srcArr, result, cycles): for c in range(cycles): for x in range(self.w): for y in range(self.h): a = srcArr[x:x+self.shape[0], y:y+self.shape[1]] if a.shape != (self.shape[0], self.shape[1]): print(a.shape) continue self.net.learn(a, result[x,y], 1) def calc(self, srcArr): resArr = np.zeros(self.resultShape) for x in range(self.w): for y in range(self.h): a = srcArr[x:x+self.shape[0], y:y+self.shape[1]] if a.shape != (self.shape[0], self.shape[1]): continue if x >= self.resultShape[0] or y >= self.resultShape[1]: continue res = self.net.calc(a) resArr[x,y] = res[0,0] return resArr def learnFile(self, file, result, cycles): return self.learn(readImage(file, self.imageSize), result, cycles) def calcFile(self, file): return self.calc(readImage(file, self.imageSize)) def readImageCV(file, imageSize): img = cv2.imread(file) small = cv2.resize(img, imageSize) hsv = cv2.cvtColor(small, cv2.COLOR_BGR2HSV) return hsv[:,:,0]/255 def readImageQ(file, imageSize): img = QImage(file) if img.isNull(): return 0 img = img.convertToFormat(QImage.Format_Grayscale8) img = img.scaled(imageSize[0],imageSize[1],Qt.IgnoreAspectRatio) srcBi = img.bits() srcBi.setsize(img.width() * img.height()) srcBy = bytes(srcBi) srcW, srcH = img.width(), img.height() srcArr = np.recarray((srcH, srcW), dtype=np.uint8, buf=srcBy).view(dtype=np.uint8,type=np.ndarray) return srcArr/255 def readImageCVQ(file, imageSize): img = QImage(file) if img.isNull(): return 0 img = img.convertToFormat(QImage.Format_RGB888) img = img.scaled(imageSize[0],imageSize[1],Qt.IgnoreAspectRatio) srcBi = img.bits() srcBi.setsize(img.byteCount()) srcBy = bytes(srcBi) srcW, srcH = img.width(), img.height() bp = img.depth() // 8 srcArr = np.recarray((srcH, srcW, bp), dtype=np.uint8, buf=srcBy) srcArr = srcArr.view(dtype=np.uint8,type=np.ndarray) hsv = cv2.cvtColor(srcArr, cv2.COLOR_RGB2HSV) return hsv[:,:,0]/255 if __name__ == '__main__': readImage = readImageCVQ y = np.array([[1,0,1,0]]) firstShape = (40, 40) middleShape = (10, 10) imageSize = firstShape[0]*middleShape[0], firstShape[1]*middleShape[1] StartLearn = False if not StartLearn: pictDir = 'C:\\AllPictures' nn = ImgNN(firstShape, resultShape=middleShape, imageSize=imageSize) nn.net.syns[0] = np.loadtxt('syns_save0.txt',ndmin=nn.net.syns[0].ndim) nn.net.syns[1] = np.loadtxt('syns_save1.txt',ndmin=nn.net.syns[1].ndim) nn2 = NN([middleShape, (y.shape[1], middleShape[0]), y.shape]) nn2.syns[0] = np.loadtxt('syns2_save0.txt',ndmin=nn2.syns[0].ndim) nn2.syns[1] = np.loadtxt('syns2_save1.txt',ndmin=nn2.syns[1].ndim) files = [e.path for e in os.scandir(pictDir)] for f in files: i = readImage(f, imageSize) mid = nn.calc(i) res = nn2.calc(mid) delta = y-res v = round(np.std(delta),3) if v <= 0.3: print('Flower',f,v) ## else: ## print('No flower',f, v) else: fl = [e.path for e in os.scandir('flowers')] nofl = [e.path for e in os.scandir('noflowers')] all = fl+nofl yy = np.zeros(middleShape) np.fill_diagonal(yy,1) minFails = None lastSyns = None nextSyns = None lastSyns2 = None lastYY = yy nextYY = yy minDy = None maxDn = None for epoch in range(100): print('Epoch =', epoch) nn = ImgNN(firstShape, resultShape=middleShape, imageSize=imageSize) if not (lastSyns is None): nextSyns = lastSyns for r in range(len(nextSyns)): rand = (np.random.random(nextSyns[r].shape)-0.5)/20 nextSyns[r] = nextSyns[r] + rand nn.net.syns = nextSyns nn2 = NN([middleShape, (y.shape[1], middleShape[0]), y.shape]) for f in fl: i = readImage(f, imageSize) nn.learn(i, nextYY, 2) ## nn.learn(i, yy, 2) mid = nn.calc(i) nn2.learn(mid, y, 1000) nextSyns=None fails = 0 failFiles = [] dy = 0.0 dn = 0.0 for f in all: i = readImage(f, imageSize) mid = nn.calc(i) res = nn2.calc(mid) delta = (y-res) v = round(np.std(delta),3) #v = round(delta.sum(),3) print(f, 'res = ', res.round(2),'v =',v) if f in fl: dy += v if f in nofl: dn += v if v > 0.2 and f in fl: fails += 1 failFiles.append(f) elif v<0.2 and f in nofl: fails +=1 failFiles.append(f) print('dy =',dy,'dn =',dn) if minDy == None or dy < minDy: minDy = dy if maxDn == None or dn > maxDn: maxDn = dn if minFails == None or fails < minFails: minFails = fails lastSyns = nn.net.syns lastSyns2 = nn2.syns lastYY = nextYY else: nextYY = lastYY +(np.random.random(yy.shape)-0.5)/20 print('fails =',fails, failFiles) print('min =',minFails) if minFails <= 1: print('found!') break for i in range(len(lastSyns)): np.savetxt('syns_save%s.txt'%i, lastSyns[i]) for i in range(len(lastSyns2)): np.savetxt('syns2_save%s.txt'%i, lastSyns2[i])
      
      







ソースコードは、MITライセンスの下でgithubでも入手できます。



ボーナス ファイルパス内のOpenCVとロシア語の文字



前の記事で、OpenCVのimread関数には、ロシア語の文字が出現するパスを持つファイルの読み取りに問題があると述べました。 PyQtのQImageにはこのような問題はありませんが、画像をHSVカラースペースに変換し、カラープレーンを強調表示するためにOpenCVが必要でした。 したがって、QImageを介した画像の読み込みとOpenCVを介した変換を組み合わせました。



 def readImageCVQ(file, imageSize): img = QImage(file) if img.isNull(): return 0 img = img.convertToFormat(QImage.Format_RGB888) img = img.scaled(imageSize[0],imageSize[1],Qt.IgnoreAspectRatio) srcBi = img.bits() srcBi.setsize(img.byteCount()) srcBy = bytes(srcBi) srcW, srcH = img.width(), img.height() bp = img.depth() // 8 srcArr = np.recarray((srcH, srcW, bp), dtype=np.uint8, buf=srcBy) srcArr = srcArr.view(dtype=np.uint8,type=np.ndarray) hsv = cv2.cvtColor(srcArr, cv2.COLOR_RGB2HSV) return hsv[:,:,0]/255 ... readImage = readImageCVQ
      
      






All Articles