国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

用Python寫個自動批改作業(yè)系統(tǒng)!

共 40103字,需瀏覽 81分鐘

 ·

2024-05-09 08:07

??我的小冊 45章教程:(小白零基礎(chǔ)用Python量化股票分析小冊) ,原價299,限時特價2杯咖啡,滿100人漲10元。

作者:可口可樂沒有樂 

https://blog.csdn.net/m0_59236602/article/details/138212445

一、亮出效果

最近一些軟件的搜題、智能批改類的功能要下線。

退1024步講,要不要自己做一個自動批改的功能啊?萬一哪天孩子要用呢!

昨晚我做了一個夢,夢見我實(shí)現(xiàn)了這個功能,如下圖所示:

功能簡介:作對了,能打?qū)μ?;做錯了,能打叉號;沒做的,能補(bǔ)上答案。

醒來后,我環(huán)顧四周,趕緊再躺下,希望夢還能接上。

二、實(shí)現(xiàn)步驟

基本思路

其實(shí),搞定兩點(diǎn)就成,第一是能識別數(shù)字,第二是能切分?jǐn)?shù)字。

首先得能認(rèn)識5是5,這是前提條件,其次是能找到5、6、7、8這些數(shù)字區(qū)域的位置。

前者是圖像識別,后者是圖像切割。

  • 對于圖像識別,一般的套路是下面這樣的(CNN卷積神經(jīng)網(wǎng)絡(luò)):
  • 對于圖像切割,一般的套路是下面的這樣(橫向縱向投影法):

既然思路能走得通,那么咱們先搞圖像識別。準(zhǔn)備數(shù)據(jù)->訓(xùn)練數(shù)據(jù)并保存模型->使用訓(xùn)練模型預(yù)測結(jié)果。

2.1 準(zhǔn)備數(shù)據(jù)

對于男友,找一個油嘴滑舌的花花公子,不如找一個悶葫蘆IT男,親手把他培養(yǎng)成你期望的樣子。

咱們不用什么官方的mnist數(shù)據(jù)集,因?yàn)槟鞘枪俜降?,不是你的,你想要添加±×÷它也沒有。

有些通用的數(shù)據(jù)集,雖然很強(qiáng)大,很方便,但是一旦放到你的場景中,效果一點(diǎn)也不如你的愿。

只有訓(xùn)練自己手里的數(shù)據(jù),然后自己用起來才順手。更重要的是,我們享受創(chuàng)造的過程。

假設(shè),我們只給口算做識別,那么我們需要的圖片數(shù)據(jù)有如下幾類:

索引:0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
字符:0 1 2 3 4 5 6 7 8 9  =  +  -  ×  ÷

如果能識別這些,基本上能滿足整數(shù)的加減乘除運(yùn)算了。

好了,圖片哪里來?!

是啊,圖片哪里來?

嚇得我差點(diǎn)從夢里醒來,500萬都規(guī)劃好該怎么花了,居然雙色球還沒有選號!

夢里,一個老者跟我說,圖片要自己生成。我問他如何生成,他呵呵一笑,消失在迷霧中……

仔細(xì)一想,其實(shí)也不難,打字我們總會吧,生成數(shù)字無非就是用代碼把字寫在圖片上。

字之所以能展示,主要是因?yàn)橛凶煮w的支撐。

如果你用的是windows系統(tǒng),那么打開KaTeX parse error: Undefined control sequence: \Windows at position 3: C:\?W?i?n?d?o?w?s?\Fonts這個文件夾,你會發(fā)現(xiàn)好多字體。

我們寫代碼調(diào)用這些字體,然后把它打印到一張圖片上,是不是就有數(shù)據(jù)了。

而且這些數(shù)據(jù)完全是由我們控制的,想多就多,想少就少,想數(shù)字、字母、漢字、符號都可以,今天你搞出來數(shù)字識別,也就相當(dāng)于你同時擁有了所有識別!想想還有點(diǎn)小激動呢!

看看,這就是打工和創(chuàng)業(yè)的區(qū)別。你用別人的數(shù)據(jù)相當(dāng)于打工,你是不用操心,但是他給你什么你才有什么。自己造數(shù)據(jù)就相當(dāng)于創(chuàng)業(yè),雖然前期辛苦,你可以完全自己把握節(jié)奏,需要就加上,沒用就去掉。

2.1.1 準(zhǔn)備字體

建一個fonts文件夾,從字體庫里拷一部分字體放進(jìn)來,我這里是拷貝了13種字體文件。

好的,準(zhǔn)備工作做好了,肯定很累吧,休息休息休息,一會兒再搞!

2.1.2 生成圖片

代碼如下,可以直接運(yùn)行。

from __future__ import print_function
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import os
import shutil
import time

# %% 要生成的文本
label_dict = {0: '0', 1: '1', 2: '2', 3: '3', 4: '4', 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10: '=', 11: '+', 12: '-', 13: '×', 14: '÷'}

# 文本對應(yīng)的文件夾,給每一個分類建一個文件
for value,char in label_dict.items():
    train_images_dir = "dataset"+"/"+str(value)
    if os.path.isdir(train_images_dir):
        shutil.rmtree(train_images_dir)
    os.makedirs(train_images_dir)

# %% 生成圖片
def makeImage(label_dict, font_path, width=24, height=24, rotate = 0):

    # 從字典中取出鍵值對
    for value,char in label_dict.items():
        # 創(chuàng)建一個黑色背景的圖片,大小是24*24
        img = Image.new("RGB", (width, height), "black"
        draw = ImageDraw.Draw(img)
        # 加載一種字體,字體大小是圖片寬度的90%
        font = ImageFont.truetype(font_path, int(width*0.9))
        # 獲取字體的寬高
        font_width, font_height = draw.textsize(char, font)
        # 計算字體繪制的x,y坐標(biāo),主要是讓文字畫在圖標(biāo)中心
        x = (width - font_width-font.getoffset(char)[0]) / 2
        y = (height - font_height-font.getoffset(char)[1]) / 2
        # 繪制圖片,在那里畫,畫啥,什么顏色,什么字體
        draw.text((x,y), char, (255, 255, 255), font)
        # 設(shè)置圖片傾斜角度
        img = img.rotate(rotate)
        # 命名文件保存,命名規(guī)則:dataset/編號/img-編號_r-選擇角度_時間戳.png
        time_value = int(round(time.time() * 1000))
        img_path = "dataset/{}/img-{}_r-{}_{}.png".format(value,value,rotate,time_value)
        img.save(img_path)
        
# %% 存放字體的路徑
font_dir = "./fonts"
for font_name in os.listdir(font_dir):
    # 把每種字體都取出來,每種字體都生成一批圖片
    path_font_file = os.path.join(font_dir, font_name)
    # 傾斜角度從-10到10度,每個角度都生成一批圖片
    for k in range(-10, 10, 1): 
        # 每個字符都生成圖片
        makeImage(label_dict, path_font_file, rotate = k)

上面純代碼不到30行,相信大家應(yīng)該能看懂!看不懂不是我的讀者。

核心代碼就是畫文字。

draw.text((x,y), char, (255, 255, 255), font)   

翻譯一下就是:使用某字體在黑底圖片的(x,y)位置寫白色的char符號。

核心邏輯就是三層循環(huán)。

如果代碼你運(yùn)行的沒有問題,最終會生成如下結(jié)果:

好了,數(shù)據(jù)準(zhǔn)備好了??偣?5個文件夾,每個文件夾下對應(yīng)的各種字體各種傾斜角的字符圖片3900個(字符15類×字體13種×角度20個),圖片的大小是24×24像素。

有了數(shù)據(jù),我們就可以再進(jìn)行下一步了,下一步是訓(xùn)練使用數(shù)據(jù)。

2.2 訓(xùn)練數(shù)據(jù)

2.2.1 構(gòu)建模型

你先看代碼,外行感覺好深奧,內(nèi)行偷偷地笑。

# %% 導(dǎo)入必要的包 
import tensorflow as tf
import numpy as np
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
import pathlib
import cv2

# %% 構(gòu)建模型
def create_model():
    model = Sequential([
        layers.experimental.preprocessing.Rescaling(1./255, input_shape=(24, 24, 1)),
        layers.Conv2D(24,3,activation='relu'),
        layers.MaxPooling2D((2,2)),
        layers.Conv2D(64,3, activation='relu'),
        layers.MaxPooling2D((2,2)),
        layers.Flatten(),
        layers.Dense(128, activation='relu'),
        layers.Dense(15)]
    )
    
    model.compile(optimizer='adam',
                loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
                metrics=['accuracy'])

    return model

這個模型的序列是下面這樣的,作用是輸入一個圖片數(shù)據(jù),經(jīng)過各個層揉搓,最終預(yù)測出這個圖片屬于哪個分類。

這么多層都是干什么的,有什么用?和衣服一樣,肯定是有用的,內(nèi)衣、襯衣、毛衣、棉衣各有各的用處。

2.2.2 卷積層 Conv2D

各個職能部門的調(diào)查員,搜集和整理某單位區(qū)域內(nèi)的特定數(shù)據(jù)。我們輸入的是一個圖像,它是由像素組成的,這就是R e s c a l i n g ( 1. / 255 , i n p u t s h a p e = ( 24 , 24 , 1 ) ) Rescaling(1./255, input_shape=(24, 24, 1))Rescaling(1./255,input shape=(24,24,1))中,input_shape輸入形狀是24*24像素1個通道(彩色是RGB 3個通道)的圖像。

卷積層代碼中的定義是Conv2D(24,3),意思是用3*3像素的卷積核,去提取24個特征。

我把圖轉(zhuǎn)到地圖上來,你就能理解了。以我大濟(jì)南的市中區(qū)為例子。

卷積的作用就相當(dāng)于從地圖的某級單位區(qū)域中收集多組特定信息。比如以小區(qū)為單位去提取住宅數(shù)量、車位數(shù)量、學(xué)校數(shù)量、人口數(shù)、年收入、學(xué)歷、年齡等等24個維度的信息。小區(qū)相當(dāng)于卷積核。

提取完成之后是這樣的。

第一次卷積之后,我們從市中區(qū)得到N個小區(qū)的數(shù)據(jù)。

卷積是可以進(jìn)行多次的。

比如在小區(qū)卷積之后,我們還可在小區(qū)的基礎(chǔ)上再來一次卷積,在卷積就是街道了。

通過再次以街道為單位卷積小區(qū),我們就從市中區(qū)得到了N個街道的數(shù)據(jù)。

這就是卷積的作用。

通過一次次卷積,就把一張大圖,通過特定的方法卷起來,最終留下來的是固定幾組有目的數(shù)據(jù),以此方便后續(xù)的評選決策。這是評選一個區(qū)的數(shù)據(jù),要是評選濟(jì)南市,甚至山東省,也是這么卷積。這和現(xiàn)實(shí)生活中評選文明城市、經(jīng)濟(jì)強(qiáng)省也是一個道理。

2.2.3 池化層 MaxPooling2D

說白了就是四舍五入。

計算機(jī)的計算能力是強(qiáng)大的,比你我快,但也不是不用考慮成本。我們當(dāng)然希望它越快越好,如果一個方法能省一半的時間,我們肯定愿意用這種方法。

池化層干的就是這個事情。池化的代碼定義是這樣的M a x P o o l i n g 2 D ( ( 2 , 2 ) ) MaxPooling2D((2,2))MaxPooling2D((2,2)),這里是最大值池化。其中(2,2)是池化層的大小,其實(shí)就是在2*2的區(qū)域內(nèi),我們認(rèn)為這一片可以合成一個單位。

再以地圖舉個例子,比如下面的16個格子里的數(shù)據(jù),是16個街道的學(xué)校數(shù)量。

為了進(jìn)一步提高計算效率,少計算一些數(shù)據(jù),我們用2*2的池化層進(jìn)行池化。

池化的方格是4個街道合成1個,新單位學(xué)校數(shù)量取成員中學(xué)校數(shù)量最大(也有取最小,取平均多種池化)的那一個。池化之后,16個格子就變?yōu)榱?個格子,從而減少了數(shù)據(jù)。

這就是池化層的作用。

2.2.4 全連接層 Dense

弱水三千,只取一瓢。

在這里,它其實(shí)是一個分類器。

我們構(gòu)建它時,代碼是這樣的D e n s e ( 15 ) Dense(15)Dense(15)。

它所做的事情,不管你前面是怎么樣,有多少維度,到我這里我要強(qiáng)行轉(zhuǎn)化為固定的通道。

比如識別字母a~z,我有500個神經(jīng)元參與判斷,但是最終輸出結(jié)果就是26個通道(a,b,c,……,y,z)。

我們這里總共有15類字符,所以是15個通道。給定一個輸入后,輸出為每個分類的概率。

注意:上面都是二維的輸入,比如24×24,但是全連接層是一維的,所以代碼中使用了l a y e r s . F l a t t e n ( ) layers.Flatten()layers.Flatten()將二維數(shù)據(jù)拉平為一維數(shù)據(jù)([[11,12],[21,22]]->[11,12,21,22])。

對于總體的模型,調(diào)用m o d e l . s u m m a r y ( ) model.summary()model.summary()打印序列的網(wǎng)絡(luò)結(jié)構(gòu)如下:

_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
rescaling_2 (Rescaling)      (None, 24, 24, 1)         0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 22, 22, 24)        240       
_________________________________________________________________
max_pooling2d_4 (MaxPooling2 (None, 11, 11, 24)        0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 9, 9, 64)          13888     
_________________________________________________________________
max_pooling2d_5 (MaxPooling2 (None, 4, 4, 64)          0         
_________________________________________________________________
flatten_2 (Flatten)          (None, 1024)              0         
_________________________________________________________________
dense_4 (Dense)              (None, 128)               131200    
_________________________________________________________________
dense_5 (Dense)              (None, 15)                1935      
=================================================================
Total params: 147,263
Trainable params: 147,263
Non-trainable params: 0
_________________________________________________________________

我們看到conv2d_5 (Conv2D) (None, 9, 9, 64) 經(jīng)過2*2的池化之后變?yōu)閙ax_pooling2d_5 (MaxPooling2 (None, 4, 4, 64)。(None, 4, 4, 64) 再經(jīng)過F l a t t e n FlattenFlatten拉成一維之后變?yōu)?None, 1024),經(jīng)過全連接變?yōu)?None, 128)再一次全連接變?yōu)?None, 15),15就是我們的最終分類。這一切都是我們設(shè)計的。

m o d e l . c o m p i l e model.compilemodel.compile就是配置模型的幾個參數(shù),這個現(xiàn)階段記住就可以。

2.2.5 訓(xùn)練數(shù)據(jù)

執(zhí)行就完了。

# 統(tǒng)計文件夾下的所有圖片數(shù)量
data_dir = pathlib.Path('dataset')
# 從文件夾下讀取圖片,生成數(shù)據(jù)集
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
    data_dir, # 從哪個文件獲取數(shù)據(jù)
    color_mode="grayscale"# 獲取數(shù)據(jù)的顏色為灰度
    image_size=(24, 24), # 圖片的大小尺寸
    batch_size=32 # 多少個圖片為一個批次
)
# 數(shù)據(jù)集的分類,對應(yīng)dataset文件夾下有多少圖片分類
class_names = train_ds.class_names
# 保存數(shù)據(jù)集分類
np.save("class_name.npy", class_names)
# 數(shù)據(jù)集緩存處理
AUTOTUNE = tf.data.experimental.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=AUTOTUNE)
# 創(chuàng)建模型
model = create_model()
# 訓(xùn)練模型,epochs=10,所有數(shù)據(jù)集訓(xùn)練10遍
model.fit(train_ds,epochs=10)
# 保存訓(xùn)練后的權(quán)重
model.save_weights('checkpoint/char_checkpoint')

執(zhí)行之后會輸出如下信息:

Found 3900 files belonging to 15 classes. 
Epoch 1/10 122/122 [=========] - 2s 19ms/step - loss: 0.5795 - accuracy: 0.8615 
Epoch 2/10 122/122 [=========] - 2s 18ms/step - loss: 0.0100 - accuracy: 0.9992 
Epoch 3/10 122/122 [=========] - 2s 19ms/step - loss: 0.0027 - accuracy: 1.0000 
Epoch 4/10 122/122 [=========] - 2s 19ms/step - loss: 0.0013 - accuracy: 1.0000 
Epoch 5/10 122/122 [=========] - 2s 20ms/step - loss: 8.4216e-04 - accuracy: 1.0000 
Epoch 6/10 122/122 [=========] - 2s 18ms/step - loss: 5.5273e-04 - accuracy: 1.0000 
Epoch 7/10 122/122 [=========] - 3s 21ms/step - loss: 4.0966e-04 - accuracy: 1.0000 
Epoch 8/10 122/122 [=========] - 2s 20ms/step - loss: 3.0308e-04 - accuracy: 1.0000 
Epoch 9/10 122/122 [=========] - 3s 23ms/step - loss: 2.3446e-04 - accuracy: 1.0000 
Epoch 10/10 122/122 [=========] - 3s 21ms/step - loss: 1.8971e-04 - accuracy: 1.0000

我們看到,第3遍時候,準(zhǔn)確率達(dá)到100%了。最后結(jié)束的時候,我們發(fā)現(xiàn)文件夾checkpoint下多了幾個文件:

char_checkpoint.data-00000-of-00001
char_checkpoint.index
checkpoint   

上面那幾個文件是訓(xùn)練結(jié)果,訓(xùn)練保存之后就不用動了。后面可以直接用這些數(shù)據(jù)進(jìn)行預(yù)測。

2.3 預(yù)測數(shù)據(jù)

終于到了享受成果的時候了。

# 設(shè)置待識別的圖片
img1=cv2.imread('img1.png',0) 
img2=cv2.imread('img2.png',0) 
imgs = np.array([img1,img2])
# 構(gòu)建模型
model = create_model()
# 加載前期訓(xùn)練好的權(quán)重
model.load_weights('checkpoint/char_checkpoint')
# 讀出圖片分類
class_name = np.load('class_name.npy')
# 預(yù)測圖片,獲取預(yù)測值
predicts = model.predict(imgs) 
results = [] # 保存結(jié)果的數(shù)組
for predict in predicts: #遍歷每一個預(yù)測結(jié)果
    index = np.argmax(predict) # 尋找最大值
    result = class_name[index] # 取出字符
    results.append(result)
print(results)

我們找兩張圖片img1.png,img2.png,一張是數(shù)字6,一張是數(shù)字8,兩張圖放到代碼同級目錄下,驗(yàn)證一下識別效果如何。

圖片要通過cv2.imread(‘img1.png’,0) 轉(zhuǎn)化為二維數(shù)組結(jié)構(gòu),0參數(shù)是灰度圖片。經(jīng)過處理后,圖片轉(zhuǎn)成的數(shù)組是如下所示(24,24)的結(jié)構(gòu):

我們要同時驗(yàn)證兩張圖,所以把兩張圖再組成imgs放到一起,imgs的結(jié)構(gòu)是(2,24,24)。

下面是構(gòu)建模型,然后加載權(quán)重。通過調(diào)用predicts = model.predict(imgs)將imgs傳遞給模型進(jìn)行預(yù)測得出predicts。

predicts的結(jié)構(gòu)是(2,15),數(shù)值如下面所示:

[[ 16.134243 -12.10675 -1.1994154 -27.766754 -43.4324 -9.633694 -12.214878 1.6287893 2.562174 3.2222707 13.834648 28.254173 -6.102874 16.76582 7.2586184] [ 5.022571 -8.762314 -6.7466817 -23.494259 -30.170597 2.4392672 -14.676962 5.8255725 8.855118 -2.0998626 6.820853 7.6578817 1.5132296 24.4664 2.4192357]]

意思是有2個預(yù)測結(jié)果,每一個圖片的預(yù)測結(jié)果有15種可能。

然后根據(jù) index = np.argmax(predict) 找出最大可能的索引。

根據(jù)索引找到字符的數(shù)值結(jié)果是[‘6’, ‘8’]。

下面是數(shù)據(jù)在內(nèi)存中的監(jiān)控:

可見,我們的預(yù)測是準(zhǔn)確的。

下面,我們將要把圖片中數(shù)字切割出來,進(jìn)行識別了。

之前我們準(zhǔn)備了數(shù)據(jù),訓(xùn)練了數(shù)據(jù),并且拿圖片進(jìn)行了識別,識別結(jié)果正確。

到目前為止,看來問題不大……沒有大問題,有問題也大不了。

下面就是把圖片進(jìn)行切割識別了。

下面這張大圖片,怎么把它搞一搞,搞成單個小數(shù)字的圖片。

2.4 切割圖像

上帝說要有光,就有了光。

于是,當(dāng)光投過來時,物體的背后就有了影。

我們就知道了,有影的地方就有東西,沒影的地方是空白。

這就是投影。

這個簡單的道理放在圖像切割上也很實(shí)用。

我們把文字的像素做個投影,這樣我們就知道某個區(qū)間有沒有文字,并且知道這個區(qū)間文字是否集中。

下面是示意圖:

2.4.1 投影大法

最有效的方法,往往都是用循環(huán)實(shí)現(xiàn)的。

要計算投影,就得一個像素一個像素地數(shù),查看有幾個像素,然后記錄下這一行有N個像素點(diǎn)。如此循環(huán)。

首先導(dǎo)入包:

import numpy as np
import cv2
from PIL import Image, ImageDraw, ImageFont
import PIL
import matplotlib.pyplot as plt
import os
import shutil
from numpy.core.records import array
from numpy.core.shape_base import block
import time

比如說要看垂直方向的投影,代碼如下:

# 整幅圖片的Y軸投影,傳入圖片數(shù)組,圖片經(jīng)過二值化并反色
def img_y_shadow(img_b):
    ### 計算投影 ###
    (h,w)=img_b.shape
    # 初始化一個跟圖像高一樣長度的數(shù)組,用于記錄每一行的黑點(diǎn)個數(shù)
    a=[0 for z in range(0,h)]
    # 遍歷每一列,記錄下這一列包含多少有效像素點(diǎn)
    for i in range(0,h):          
        for j in range(0,w):      
            if img_b[i,j]==255:     
                a[i]+=1  
    return a

最終得到是這樣的結(jié)構(gòu):[0, 79, 67, 50, 50, 50, 109, 137, 145, 136, 125, 117, 123, 124, 134, 71, 62, 68, 104, 102, 83, 14, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, ……38, 44, 56, 106, 97, 83, 0, 0, 0, 0, 0, 0, 0]表示第幾行總共有多少個像素點(diǎn),第1行是0,表示是空白的白紙,第2行有79個像素點(diǎn)。

如果我們想要從視覺呈現(xiàn)出來怎么處理呢?那可以把它立起來拉直畫出來。

# 展示圖片
def img_show_array(a):
    plt.imshow(a)
    plt.show()
    
# 展示投影圖, 輸入?yún)?shù)arr是圖片的二維數(shù)組,direction是x,y軸
def show_shadow(arr, direction = 'x'):

    a_max = max(arr)
    if direction == 'x'# x軸方向的投影
        a_shadow = np.zeros((a_max, len(arr)), dtype=int)
        for i in range(0,len(arr)):
            if arr[i] == 0:
                continue
            for j in range(0, arr[i]):
                a_shadow[j][i] = 255
    elif direction == 'y'# y軸方向的投影
        a_shadow = np.zeros((len(arr),a_max), dtype=int)
        for i in range(0,len(arr)):
            if arr[i] == 0:
                continue
            for j in range(0, arr[i]):
                a_shadow[i][j] = 255

    img_show_array(a_shadow)   

我們來試驗(yàn)一下效果:

我們將上面的原圖片命名為question.jpg放到代碼同級目錄。

# 讀入圖片
img_path = 'question.jpg'
img=cv2.imread(img_path,0) 
thresh = 200 
# 二值化并且反色
ret,img_b=cv2.threshold(img,thresh,255,cv2.THRESH_BINARY_INV) 

二值化并反色后的變化如下所示:

上面的操作很有作用,通過二值化,過濾掉雜色,通過反色將黑白對調(diào),原來白紙區(qū)域都是255,現(xiàn)在黑色都是0,更利于計算。

計算投影并展示的代碼:

img_y_shadow_a = img_y_shadow(img_b)
show_shadow(img_y_shadow_a, 'y'# 如果要顯示投影

下面的圖是上面圖在Y軸上的投影

從視覺上看,基本上能區(qū)分出來哪一行是哪一行。

2.4.2 根據(jù)投影找區(qū)域

最有效的方法,往往還得用循環(huán)來實(shí)現(xiàn)。

上面投影那張圖,你如何計算哪里到哪里是一行,雖然肉眼可見,但是計算機(jī)需要規(guī)則和算法。

# 圖片獲取文字塊,傳入投影列表,返回標(biāo)記的數(shù)組區(qū)域坐標(biāo)[[左,上,右,下]]
def img2rows(a,w,h):
    
    ### 根據(jù)投影切分圖塊 ### 
    inLine = False # 是否已經(jīng)開始切分
    start = 0 # 某次切分的起始索引
    mark_boxs = []
    for i in range(0,len(a)):        
        if inLine == False and a[i] > 10:
            inLine = True
            start = i
        # 記錄這次選中的區(qū)域[左,上,右,下],上下就是圖片,左右是start到當(dāng)前
        elif i-start >5 and a[i] < 10 and inLine:
            inLine = False
            if i-start > 10:
                top = max(start-1, 0)
                bottom = min(h, i+1)
                box = [0, top, w, bottom]
                mark_boxs.append(box) 
                
    return mark_boxs

通過投影,計算哪些區(qū)域在一定范圍內(nèi)是連續(xù)的,如果連續(xù)了很長時間,我們就認(rèn)為是同一區(qū)域,如果斷開了很長一段時間,我們就認(rèn)為是另一個區(qū)域。

通過這項(xiàng)操作,我們就可以獲得Y軸上某一行的上下兩個邊界點(diǎn)的坐標(biāo),再結(jié)合圖片寬度,其實(shí)我們也就知道了一行圖片的四個頂點(diǎn)的坐標(biāo)了mark_boxs存下的是[坐,上,右,下]。

如果調(diào)用如下代碼:

(img_h,img_w)=img.shape
row_mark_boxs = img2rows(img_y_shadow_a,img_w,img_h)
print(row_mark_boxs)

我們獲取到的是所有識別出來每行圖片的坐標(biāo),格式是這樣的:[[0, 26, 596, 52], [0, 76, 596, 103], [0, 130, 596, 155], [0, 178, 596, 207], [0, 233, 596, 259], [0, 282, 596, 311], [0, 335, 596, 363], [0, 390, 596, 415]]

2.4.3 根據(jù)區(qū)域切圖片

最有效的方法,最終也得用循環(huán)來實(shí)現(xiàn)。這也是計算機(jī)體現(xiàn)它強(qiáng)大的地方。

# 裁剪圖片,img 圖片數(shù)組, mark_boxs 區(qū)域標(biāo)記
def cut_img(img, mark_boxs):

    img_items = [] # 存放裁剪好的圖片
    for i in range(0,len(mark_boxs)):
        img_org = img.copy()
        box = mark_boxs[i]
        # 裁剪圖片
        img_item = img_org[box[1]:box[3], box[0]:box[2]]
        img_items.append(img_item)
    return img_items  

這一步驟是拿著方框,從大圖上用小刀劃下小圖,核心代碼是img_org[box[1]:box[3], box[0]:box[2]]圖片裁剪,參數(shù)是數(shù)組的[上:下,左:右],獲取的數(shù)據(jù)還是二維的數(shù)組。

如果保存下來:

# 保存圖片
def save_imgs(dir_name, imgs):
 
    if os.path.exists(dir_name):
        shutil.rmtree(dir_name) 
    if not os.path.exists(dir_name):    
        os.makedirs(dir_name)

    img_paths = []
    for i in range(0,len(imgs)):
        file_path = dir_name+'/part_'+str(i)+'.jpg'
        cv2.imwrite(file_path,imgs[i])
        img_paths.append(file_path)
    
    return img_paths

# 切圖并保存
row_imgs = cut_img(img, row_mark_boxs)
imgs = save_imgs('rows', row_imgs) # 如果要保存切圖
print(imgs)

圖片是下面這樣的:

2.4.4 循環(huán)可去油膩

還是循環(huán)。橫著行我們掌握了,那么針對每一行圖片,我們豎著切成三塊是不是也會了,一個道理。

需要注意的是,橫豎是稍微有區(qū)別的,下面是上圖的x軸投影。

橫著的時候,字與字之間本來就是有空隙的,然后塊與塊也有空隙,這個空隙的度需要掌握好,以便更好地區(qū)分出來是字的間距還是算式塊的間距。

幸好,有種方法叫膨脹。

膨脹對人來說不積極,但是對于技術(shù)來說,不管是膨脹(dilate),還是腐蝕(erode),只要能達(dá)到目的,都是好的。

kernel=np.ones((3,3),np.uint8)  # 膨脹核大小
row_img_b=cv2.dilate(img_b,kernel,iterations=6) # 圖像膨脹6次

膨脹之后再投影,就很好地區(qū)分出了塊。

根據(jù)投影裁剪之后如下圖所示:

同理,不膨脹可截取單個字符。

這樣,這是一塊區(qū)域的字符。

一行的,一頁的,通過循環(huán),都可以截取出來。

有了圖片,就可以識別了。有了位置,就可以判斷識別結(jié)果的關(guān)系了。

下面提供一些代碼,這些代碼不全,有些函數(shù)你可能找不到,但是思路可以參考,詳細(xì)的代碼可以去我的github去看。

def divImg(img_path, save_file = False):

    img_o=cv2.imread(img_path,1) 
    # 讀入圖片
    img=cv2.imread(img_path,0) 
    (img_h,img_w)=img.shape
    thresh = 200
    # 二值化整個圖,用于分行
    ret,img_b=cv2.threshold(img,thresh,255,cv2.THRESH_BINARY_INV) 

    # 計算投影,并截取整個圖片的行
    img_y_shadow_a = img_y_shadow(img_b)
    row_mark_boxs = img2rows(img_y_shadow_a,img_w,img_h)
    # 切行的圖片,切的是原圖
    row_imgs = cut_img(img, row_mark_boxs)
    all_mark_boxs = []
    all_char_imgs = []
    # ===============從行切塊======================
    for i in range(0,len(row_imgs)):
        row_img = row_imgs[i]
        (row_img_h,row_img_w)=row_img.shape
        # 二值化一行的圖,用于切塊
        ret,row_img_b=cv2.threshold(row_img,thresh,255,cv2.THRESH_BINARY_INV)
        kernel=np.ones((3,3),np.uint8)
        #圖像膨脹6次
        row_img_b_d=cv2.dilate(row_img_b,kernel,iterations=6)
        img_x_shadow_a = img_x_shadow(row_img_b_d)
        block_mark_boxs = row2blocks(img_x_shadow_a, row_img_w, row_img_h)
        row_char_boxs = []
        row_char_imgs = []
        # 切塊的圖,切的是原圖
        block_imgs = cut_img(row_img, block_mark_boxs)
        if save_file:
            b_imgs = save_imgs('cuts/row_'+str(i), block_imgs) # 如果要保存切圖
            print(b_imgs)
        # =============從塊切字====================
        for j in range(0,len(block_imgs)):
            block_img = block_imgs[j]
            (block_img_h,block_img_w)=block_img.shape
            # 二值化塊,因?yàn)橐凶址麍D片了
            ret,block_img_b=cv2.threshold(block_img,thresh,255,cv2.THRESH_BINARY_INV)
            block_img_x_shadow_a = img_x_shadow(block_img_b)
            row_top = row_mark_boxs[i][1]
            block_left = block_mark_boxs[j][0]
            char_mark_boxs,abs_char_mark_boxs = block2chars(block_img_x_shadow_a, block_img_w, block_img_h,row_top,block_left)
            row_char_boxs.append(abs_char_mark_boxs)
            # 切的是二值化的圖
            char_imgs = cut_img(block_img_b, char_mark_boxs, True)
            row_char_imgs.append(char_imgs)
            if save_file:
                c_imgs = save_imgs('cuts/row_'+str(i)+'/blocks_'+str(j), char_imgs) # 如果要保存切圖
                print(c_imgs)
        all_mark_boxs.append(row_char_boxs)
        all_char_imgs.append(row_char_imgs)


最后返回的值是3個,all_mark_boxs是標(biāo)記的字符位置的坐標(biāo)集合。[左,上,右,下]是指某個字符在一張大圖里的坐標(biāo),打印一下是這樣的:

[[[[19, 26, 34, 53], [36, 26, 53, 53], [54, 26, 65, 53], [66, 26, 82, 53], [84, 26, 101, 53], [102, 26, 120, 53], [120, 26, 139, 53]], [[213, 26, 229, 53], [231, 26, 248, 53], [249, 26, 268, 53], [268, 26, 285, 53]], [[408, 26, 426, 53], [427, 26, 437, 53], [438, 26, 456, 53], [456, 26, 474, 53], [475, 26, 492, 53]]], [[[20, 76, 36, 102], [38, 76, 48, 102], [50, 76, 66, 102], [67, 76, 85, 102], [85, 76, 104, 102]], [[214, 76, 233, 102], [233, 76, 250, 102], [252, 76, 268, 102], [270, 76, 287, 102]], [[411, 76, 426, 102], [428, 76, 445, 102], [446, 76, 457, 102], [458, 76, 474, 102], [476, 76, 493, 102], [495, 76, 511, 102]]]]

它是有結(jié)構(gòu)的。它的結(jié)構(gòu)是:

all_char_imgs這個返回值,里面是上面坐標(biāo)結(jié)構(gòu)對應(yīng)位置的圖片。img_o就是原圖了。

2.5 識別

循環(huán),循環(huán),還是TM循環(huán)!

對于識別,2.3 預(yù)測數(shù)據(jù)已經(jīng)講過了,那次是對于2張獨(dú)立圖片的識別,現(xiàn)在我們要對整張大圖切分后的小圖集合進(jìn)行識別,這就又用到了循環(huán)。

翠花,上代碼!

all_mark_boxs,all_char_imgs,img_o = divImg(path,save)
model = cnn.create_model()
model.load_weights('checkpoint/char_checkpoint')
class_name = np.load('class_name.npy')

# 遍歷行
for i in range(0,len(all_char_imgs)):
    row_imgs = all_char_imgs[i]
    # 遍歷塊
    for j in range(0,len(row_imgs)):
        block_imgs = row_imgs[j]
        block_imgs = np.array(block_imgs)
        results = cnn.predict(model, block_imgs, class_name)
        print('recognize result:',results)

上面代碼做的就是以塊為單位,傳遞給神經(jīng)網(wǎng)絡(luò)進(jìn)行預(yù)測,然后返回識別結(jié)果。

針對這張圖,我們來進(jìn)行裁剪和識別。

看底部的最后一行

recognize result: ['1''0''12''2''10']
recognize result: ['8''12''6''10']
recognize result: ['1''0''12''7''10']

結(jié)果是索引,不是真實(shí)的字符,我們根據(jù)字典10: ‘=’, 11: ‘+’, 12: ‘-’, 13: ‘×’, 14: '÷’轉(zhuǎn)換過來之后結(jié)果是:

recognize result: ['1''0''-''2''=']
recognize result: ['8''-''6''=']
recognize result: ['1''0''-''7''=']

和圖片是對應(yīng)的:

2.6 計算并反饋

循環(huán)……

我們獲取到了10-2=、8-6=2,也獲取到了他們在原圖的位置坐標(biāo)[左,上,右,下],那么怎么把結(jié)果反饋到原圖上呢?

往往到這里就剩最后一步了。

再來溫習(xí)一遍需求:作對了,能打?qū)μ枺蛔鲥e了,能打叉號;沒做的,能補(bǔ)上答案。

實(shí)現(xiàn)分兩步走:計算(是作對做錯還是沒錯)和反饋(把預(yù)期結(jié)果寫到原圖上)。

2.6.1 計算 python有個函數(shù)很強(qiáng)大,就是eval函數(shù),能計算字符串算式,比如直接計算eval(“5+3-2”)。

所以,一切都靠它了。

# 計算數(shù)值并返回結(jié)果  參數(shù)chars:['8', '-', '6', '=']
def calculation(chars):
    cstr = ''.join(chars)
    result = ''
    if("=" in cstr): # 有等號
        str_arr = cstr.split('=')
        c_str = str_arr[0]
        r_str = str_arr[1]
        c_str = c_str.replace("×","*")
        c_str = c_str.replace("÷","/"
        try:
            c_r = int(eval(c_str))
        except Exception as e:
            print("Exception",e)

        if r_str == "":
            result = c_r
        else:
            if str(c_r) == str(r_str):
                result = "√"
            else:
                result = "×"

    return result

執(zhí)行之后獲得的結(jié)果是:

recognize result: ['8''×''4''=']
calculate result: 32
recognize result: ['2''-''1''=''1']
calculate result: √
recognize result: ['1''0''-''5''=']
calculate result: 5
2.6.2 反饋

有了結(jié)果之后,把結(jié)果寫到圖片上,這是最后一步,也是最簡單的一步。

但是實(shí)現(xiàn)起來,居然很繁瑣。

得找坐標(biāo)吧,得計算結(jié)果呈現(xiàn)的位置吧,我們還想標(biāo)記不同的顏色,比如對了是綠色,錯了是紅色,補(bǔ)齊答案是灰色。

下面代碼是在一個圖img上,把文本內(nèi)容text畫到(left,top)位置,以特定顏色和大小。

# 繪制文本
def cv2ImgAddText(img, text, left, top, textColor=(255, 0, 0), textSize=20):
    if (isinstance(img, np.ndarray)):  # 判斷是否OpenCV圖片類型
        img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    # 創(chuàng)建一個可以在給定圖像上繪圖的對象
    draw = ImageDraw.Draw(img)
    # 字體的格式
    fontStyle = ImageFont.truetype("fonts/fangzheng_shusong.ttf", textSize, encoding="utf-8")
    # 繪制文本
    draw.text((left, top), text, textColor, font=fontStyle)
    # 轉(zhuǎn)換回OpenCV格式
    return cv2.cvtColor(np.asarray(img), cv2.COLOR_RGB2BGR)

結(jié)合著切圖的信息、計算的信息,下面代碼提供思路參考:

# 獲取切圖標(biāo)注,切圖圖片,原圖圖圖片
all_mark_boxs,all_char_imgs,img_o = divImg(path,save)
# 恢復(fù)模型,用于圖片識別
model = cnn.create_model()
model.load_weights('checkpoint/char_checkpoint')
class_name = np.load('class_name.npy')

# 遍歷行
for i in range(0,len(all_char_imgs)):
    row_imgs = all_char_imgs[i]
    # 遍歷塊
    for j in range(0,len(row_imgs)):
        block_imgs = row_imgs[j]
        block_imgs = np.array(block_imgs)
        # 圖片識別
        results = cnn.predict(model, block_imgs, class_name)
        print('recognize result:',results)
        # 計算結(jié)果
        result = calculation(results)
        print('calculate result:',result)
        # 獲取塊的標(biāo)注坐標(biāo)
        block_mark = all_mark_boxs[i][j]
        # 獲取結(jié)果的坐標(biāo),寫在塊的最后一個字
        answer_box = block_mark[-1]
        # 計算最后一個字的位置
        x = answer_box[2] 
        y = answer_box[3]
        iw = answer_box[2] - answer_box[0]
        ih = answer_box[3] - answer_box[1]
        # 計算字體大小
        textSize =  max(iw,ih)
        # 根據(jù)結(jié)果設(shè)置字體顏色
        if str(result) == "√":
            color = (0, 255, 0)
        elif str(result) == "×":
            color = (255, 0, 0)
        else:
            color = (192, 192,192)
        # 將結(jié)果寫到原圖上
        img_o = cv2ImgAddText(img_o, str(result), answer_box[2],  answer_box[1],color, textSize)
# 將寫滿結(jié)果的原圖保存
cv2.imwrite('result.jpg', img_o)

結(jié)果是下面這樣的:



最后推薦一下我們團(tuán)隊(duì)寫的量化小冊的內(nèi)容,45篇內(nèi)容!從Python安裝,入門,數(shù)據(jù)分析,爬取股票基金的歷史+實(shí)時數(shù)據(jù),以及如何寫一個簡單量化策略,策略回測,如何看資金曲線統(tǒng)統(tǒng)都有介紹!非常超值!

歡迎訂閱:原價299 早鳥價2杯咖啡錢,即可永久閱讀。滿400人又要漲價了,現(xiàn)在的價格非常非常低,只要2杯奶茶,就可以終身訂閱+課程源碼,還有永久陪伴群。48小時無理由退款,放心食用!


往期推薦

量化: 如何用Python爬取創(chuàng)業(yè)板歷史+實(shí)時股票數(shù)據(jù)!實(shí)戰(zhàn)股票分析篇利用Pandas 9招挖掘五糧液股價!實(shí)戰(zhàn)股票數(shù)據(jù)分析篇 Pandas滾動操作 |量化股票第一步,用Python畫股票K線,雙均線圖,可視化你的股票數(shù)據(jù)!如何用Python爬取全部800多只ETF基金數(shù)據(jù)!如何用Python寫一個雙均線策略 |如何用Python開發(fā)一個多策略機(jī)器人!上篇!Python量化系列-用布林策略買五糧液能賺多少錢?只要4秒鐘!用Python 獲取上證指數(shù)34年的歷史日線數(shù)據(jù)!


入門: 最全的零基礎(chǔ)學(xué)Python的問題  | 零基礎(chǔ)學(xué)了8個月的Python  | 實(shí)戰(zhàn)項(xiàng)目 |學(xué)Python就是這條捷徑


干貨:爬取豆瓣短評,電影《后來的我們》 | 38年NBA最佳球員分析 |   從萬眾期待到口碑撲街!唐探3令人失望  | 笑看新倚天屠龍記 | 燈謎答題王 |用Python做個海量小姐姐素描圖 |碟中諜這么火,我用機(jī)器學(xué)習(xí)做個迷你推薦系統(tǒng)電影


趣味:彈球游戲  | 九宮格  | 漂亮的花 | 兩百行Python《天天酷跑》游戲!

AI: 會做詩的機(jī)器人 | 給圖片上色 | 預(yù)測收入 | 碟中諜這么火,我用機(jī)器學(xué)習(xí)做個迷你推薦系統(tǒng)電影

小工具: Pdf轉(zhuǎn)Word,輕松搞定表格和水??! | 一鍵把html網(wǎng)頁保存為pdf!|  再見PDF提取收費(fèi)! | 用90行代碼打造最強(qiáng)PDF轉(zhuǎn)換器,word、PPT、excel、markdown、html一鍵轉(zhuǎn)換 | 制作一款釘釘?shù)蛢r機(jī)票提示器! |60行代碼做了一個語音壁紙切換器天天看小姐姐!

瀏覽 100
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報
評論
圖片
表情
推薦
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 亚洲无码视频播放| 99性视频| 亚洲97| 91九色首页| 成人污污视频| 色五月婷婷丁香五月| 亚洲狠狠干| 亚洲成人网在线| 精品动漫一区二区三区| www.91在线视频| 亚洲丁香五月激情| 男女激情网站| 日韩骚逼| 欧美在线v| 亚洲五月丁香婷婷| 亚洲无码在线资源| 国产免费精彩视频| 中文字幕A片无码免费看| 日韩成人无码人妻| 亚洲熟女av中文字幕| 精品人妻在线| 做aAAAAA免费视频| 五月天青青草超碰免费公开在线观看 | 亚洲AV无码专区一级婬片毛片| www.6969成人片亚洲| 久久久精品久久久| 欧美成人免费在线| 操逼网123首页| 欧美综合网在线观看| 婷婷色在线| 91精品视频网站| 91超碰大香蕉| 国产激情在线观看视频| 狠狠操天天操| 人人操成人| 翔田千里无码| 欧美性爱中文字幕| 日韩成人一区二区三区| 狠狠干天天干| 黄色视频网站在线看| 日韩無码专区| 高清无码久久| 在线观看av中文字幕| 精品内射| 男人的天堂视频| 欧美综合精品| 九九九在线视频| 91人妻人人澡人人爽人人玩| 无码av高清| 夜夜骑免费视频| 日韩ava| h片在线播放| 欧美成在线| 人人草人人看| av天天看| 91国语又粗又大对白| 97人人干人人| 麻豆91蜜桃传媒在线观看| 国产AV一卡| 狠狠大香蕉| 人人妻人人操人人爽| 黄色片网站在线观看| 亚洲精品无码电影| 99免费在线观看视频| 97国产精品人人爽人人做| 超碰免费99| 妞干网国产| 亚洲一区图片| 性欧美丰满熟妇XXXX性久久久| 精品中文在线视频| 蜜桃黄片AV在线观看| 久热在线视频| 国产激情网站| 在线观看黄网| 久久精品大香蕉| AV在线免费观看网址| 亚洲成人影音| 无码人妻精品一区二区蜜桃漫画| 免费在线观看A| 扒开让我91看片在线看| 成人国产三级| 色图插插插| 日韩AV性爱| 久久中文字幕免费| 东京热综合影院| 日本熟女视频| www.黄| 影音av| 中文字幕第一区| 五月天国产精品| 逼特逼视频在线观看| 亚洲字幕无码| 久久久无码视频| 欧美激情另类| 久久国际精品| 亚洲一区三区| 亚洲www在线观看| 亚洲成人在线无码| 色婷婷五月天在线观看| 日本中文字幕网站| 一区二区三区免费播放| 少妇4p| 日韩精品视频一区二区三区| 影音先锋男人资源网| 蜜桃亚洲AV无码一区二区三区| 骚骚网| 成人777777免费视频色| 大地影视官网第三页入口| 国产精品被狂躁到高潮| 91社区成人影院| 亚洲天堂国产视频| 波多野结衣无码一区| 高H网站| 黄色片视频日韩| 人妻九九九| 一区无码精品| 欧美精品成人网站| 久久久国产精品在线| 丰满熟妇高潮呻吟无码| 亚洲国产另类无码| 福利一区在线观看| 好吊妞视频在线| 亚洲AV无码专区在线播放中文| 日韩一区二区三区精品| 97人妻人人澡人人爽人人| 精品少妇人妻一区二区| 不卡a12| 成人理伦A级A片在线论坛| 亚洲国产成人在线视频| 欧美黄色精品| 伊人精品A片一区二区三区| 91麻豆精品视频| 99在线国产| 嫩BBB揍BBB揍BBB| 大香蕉网伊| 亚洲高清无码中文字幕| 狠狠操AV| 3D动漫精品啪啪一区二区免费| 一区不卡| 91成人免费视频| 中文午夜福利| 超碰小说| 亚洲1234区| 特级黄色A片| 曰曰干| 成人视频A片| 伊人天天日| 亚洲精品视频免费观看| 婷婷五月无码| h片在线看| 色欲一区| 91综合视频| 日韩黄色毛片| 天天干天天日天天操| 欧美毛视频| 欧美久久一区二区三区四区视频 | 亚洲综合视频在线观看| 在线观看者亚洲| 拍拍视频| 青青草无码成人AV片| 欧洲黑人成人A版免费视频| 午夜亚洲AV永久无码精品蜜芽| 天天操天天谢| 婷婷丁香花| 人妻少妇偷人精品久久| 艹逼视频在线观看| 中文字幕一区在线| 国产午夜在线观看| 大地二中文在线观看免费鲁大师 | 亚洲无码免费视频在线观看 | 天堂网免费视频| 成人性生交片无码免费看人| 国产欧美综合一区二区| 91av一区| 国产香蕉av| 无码操逼视频| 插吧插吧网| 日韩欧美在线观看视频| 国产黄色视频观看| 一区二区三区国产精品| 亚洲熟女少妇| 欧美午夜精品成人片在线播放| 免费黄色一级片| 麻豆91精品91久久久| 中文字幕北条麻妃在线| 超碰人人操在线| 国产区AV| 成人无码区免费AV片| 17.3c一起起草| 91视频在线看| 久久久少妇| 日韩一区二区在线看在线看| 九九色热| 又大又粗又爽| 不卡免费视频| 中文字幕一区在线观看| 亚洲国产97| 午夜成人精品一区二区三区| 欧洲AV在线| 青青色在线观看| 五月丁香花| 国产成人秘免费观看一区二区三区| 欧美激情网站| 久久中文字幕无码| 国产免费AV在线观看| 日韩爆乳在线| 91欧美在线| 秋霞午夜福利| 亚洲东方在线| 玖玖婷婷| 国产精品欧美一区二区| 熟女91视频| 日韩欧美网站| 亚洲国际中文字幕在线| 二区视频在线| 亚洲成人无码网站| 天堂成人在线| 成人视频网站在线观看| 国产乱伦影片| 91欧美性爱| 麻豆自拍偷拍| 精品国产久久久| 91黄色毛片| 日韩无码视频播放| 成年人在线播放| 操逼视频91| 激情小视频在线观看| A天堂视频| 日韩欧美小视频| 久久免费精品| 五月天激情综合| 亚洲成人av在线播放| 日韩欧美第一页| 丁香五月婷婷色| 欧美日韩国产尤物主播精品| 高清无码视频在线| 国产黄片免费视频| 亚洲三级片在线视频| 一级黄色毛片| 免费观看黄色网| 人操人妻| 综合成人| 秋霞久久日| 天天天做夜夜夜爽无码| 99在线看| 成人无码区免费AV毛片| 在线一级A片| 福利在线看| 日韩无码视频网| 乌克兰毛片| 黄色影视不卡| 国产小视频在线看| 日韩无码AV一区二区| 广东BBW搡BBBB搡| 狠狠躁婷婷天天爽综合| 在桌下含她的花蒂和舌头H视频| 亚洲怡春院| 九色91视频| www.久久网| 麻豆精品国产传媒| 蜜桃视频成人app| 夜夜骚精品人妻av一区| 欧美最猛黑A片黑人猛交蜜桃视频| 亚洲精品成人无码AV在线| 51午夜| 国产午夜91人妻| 91无码精品国产AⅤ| 综合AV| 成人三级电影| 夜夜天天人人| 亚洲天堂网在线视频| 国内自拍第一页| 日韩视频三区| 日韩网站在线观看| 91无码精品国产| 欧美一级黄色性爱视频| 99精品视频免费在线观看| 欧美一级特黄A片免费看| 国产一级在线观看| 91人人妻人人妻人人澡| 京熱大亂交无碼大亂交| 91成人影片| 欧美三级欧美一级| 再深点好爽灬轻点久久国产| 天天干天天操天天射| 手机无码在线播放| 日韩高清无码毛片| 日韩91视频| 无码在线视频播放| 天天撸一撸视频| 成人午夜福利| 欧美成人综合色| 日韩熟女视频| 无码秘蜜桃一区二区| 偷拍视频图片综合网| 暖暖在线视频| 黄色无码视频| 无套内射在线| 夜夜嗨av| 色丁香视频在线观看的| 午夜日逼网站| 亚洲高清无码专区| 91久久久精品| 天天搞天天搞| 3D动漫精品啪啪一区二区免费| 青青草Av| 先锋影音成人| 国产成人av| 国产高清无码福利| 无码视频观看| 免费看一级高潮毛片| 精品永久免费| 九九偷拍| 日日夜夜草| 国内自拍无码| 成人网站在线免费观看| 天堂网2025| 军人妓女院BD高清片在线播放| 五月婷婷开心| 亚洲欧美第一页| 香蕉成人网| 欧美AⅤ视频| 久久综合久久鬼| 成人精品A片免费网站| 欧美黄色精品| 中文字幕欧美日韩| 一区二区三区四区无码在线| 亚洲V国产v欧美v久久久久久| 欧美一二三区黄色免费视屏| 草逼毛片| 欧美久久久久| 69成人国产| 国产一区二区三区视频在线观看 | 天堂免费视频| 无码三级午夜久久人妻| 久草免费电影| 天天综合字幕一区二区| 成人大片在线观看| 国产精品在线观看| 久久成人福利| 秋霞午夜福利| 无码人妻蜜桃| a天堂视频| 成人操b视频| 无码一道本一区二区无码| 麻豆精品国产| 中文无码第一页| 国产成人在线视频| 精品国产va久久久久久久| 亚洲AV成人无码精在线| 黄色A毛片| 狠狠操综合| 久久综合伊人7777777| 国产情侣在线视频| 女人高潮天天躁夜夜躁| 免费看黄色一级片| 国精品无码人妻一区二区三区免费| 各种BBwBBwBBwBBw| 91在线亚洲| 噜噜噜久久久| 欧美A级视频| 国产又黄又| 暖暖爱视频免费| 偷拍一区二区三区| 草视频| 国产在线精品自拍| 波多野结衣亚洲| 免费av中文字幕| 国产一区二区三区免费视频| 欧美黄片无码| JiZZjiZZ亚洲成熟熟妇 | 波多野结衣久久精品| 影音先锋成人资源站| 国产伦精品一级A片视频夜夜| 成人视频一区二区三区| av天堂小说网| 亚洲爱爱视频| 天天干天天干天天操| 91九九九| 蜜臀久久99精品久久| 草视频| 2021天天夜日| 91嫖妓站街按摩店老熟女| 无码不卡中文字幕| 中文字幕无码人妻| 天天插天天狠| 欧美亚洲天堂| 99精品免费观看| 三级网站在线| 免费三级毛片| 在线观看亚洲| 亚洲成人内射| www.五月天婷婷| 91久久国产综合久久91精品网站| 国产AV高潮| 男女69视频| 日日综合网| 91小仙女jK白丝袜呻吟| 在线观看中文字幕网站| 成人A片在线观看| 久久久久亚洲AV无码网影音先锋| 人妻精品| 中文字幕99页| 日韩精品一区二区三区四区蜜桃视频 | AV一区二区三区| 自拍偷拍网址| 激情无码网站| 亚洲午夜在线观看| 中国无码| 婷婷五月在线观看| 免费看黄色毛片| 91在线精品无码秘入口苹果| 色亭亭影院| 青草av在| 国产日韩欧美在线播放| 色婷婷亚洲色| 国产精品无码AV| 国产在线精品自拍| 亚洲成人AV在线| 人妻av中文无码| 国产三四区久久| 色资源站| 日韩高清精品在线| 91人人草| 国产在线1| 中文字幕综合网| 免费A片在线播放| va色婷婷亚洲在线| 99爱在线观看| 人人爽人人爽人人| 日韩欧美网站| 日韩香蕉视频| 丁香五月亭亭| AV片在线观看| 综合伊人大香蕉| 甘肃WBBBB搡wBBBB| 老熟妇一区二区三区啪啪| 西西444WWW无码视频软件| 黄网在线免费观看| 中文字幕无码观看| 日韩三级| 一区二区三区电影| www.jiujiujiu| 久久久91| 秋霞无码| 一二三区| 亚洲AV无码成人精品涩涩麻豆| 91x色| 激情男人网| 欧美a级视频| 竹菊av一区二区三区四区五区| 日韩人妻一区二区| 日韩免费视频观看| 欧美老妇大BBBBXXXX| 日韩一级片视频| 91成人网站| 人人操人人干人人操| 狠狠五月| 无码9999| 欧美精品久久久久久久久爆乳| 欧美特黄AAAAAAAAA片| 国产网站视频| 亚洲天堂网站| AV一区二区三区四区| 波多野结衣在线无码视频| 山东熟妇搡BBBB搡BBBB| 波多野结衣无码高清视频| 日韩中文字幕一区二区| 操逼视频大全| 黄色免费看| 日韩毛片在线免费观看| 国产a级毛片| 一级黄色片免费| 蜜桃在线无码| 韩国av在线| 亚欧三级| 91嫖妓站街埯店老熟女| 成人自拍视频| 国产一区二区成人久久919色| 无码AV电影在线观看| 日韩成人片| av资源免费观看| 欧美黄色一级网站| 北条麻妃一区二区三区-免费免费高清观看 | 黄色网址在线观看视频| 国产精品视频免费| 黄色大片免费在线观看| 大香蕉久久精品| 在线一区二区三区| 国产一级a毛一级a毛观看视频网站 | 亚洲一级性爱| 国产成人综合亚洲| 国产av影院| 欧美激情无码一区二区三区张丽 | 无码精品成人观看A片| 欧美性爱日韩| 久久久999| 超碰女人| 黑人毛片91久久久久久| 亚洲成人一区二区在线观看| www.天天操| 12—13女人毛片毛片| 国产激情精品视频| 免费一级黄色电影| 国产精品无码7777777| 俺去啦俺去啦| AV无码不卡| 在线无码一区| 熟妇综合| 五月婷综合| 精品乱码一区| 国产成人精品无码免费| 综合网欧美| 天天日天天噜| 亚洲AV无码第一区二区三区蜜桃| 西西人体大胆ww4444| 黄色永久网站| 怡红院成人在线| 国产性爱自拍一下| 日本中文字幕在线视频| 尹人在线视频| 免费高清无码视频在线观看| 无码av无码AV| 人人干人人摸人人操| 中文在线资源| 大香蕉偷拍视频| 久久精品综合| 中文字幕在线观看视频www| 日韩久久婷婷| 日本亚洲欧洲免费| 91精品久久久久| 欧美18禁网站| 最新毛片网站| 午夜成人国产| 999日本不卡影院| 成人视频一区二区三区| 日韩欧美第一页| 黄色免费AV| www日本高清| 最近中文字幕免费mv第一季歌词強上 | 女神思瑞精品一区二区三区| 草视频| AV无码在线免费观看| 大香蕉尹人在看| 成人福利免费视频| 国产免费黄色| 91插逼| 狠狠躁18三区二区一区免费人 | 国产福利视频在线观看| 久大香蕉| 无码人妻A片一区二区青苹果| 简单AV网| 欧美人人插| wwwav| 91成人一区二区三区| 婷婷久久婷婷| 中文在线A∨在线| 91人妻一区二区三区| 在线观看无码| 俺也去在线视频| 99在线国产| 奇米色网| 国产精品无码不卡| 国产乱婬片视频| 亚洲无码在线免费观看| 激情国产在线| 9l视频自拍蝌蚪9l成人蝌蚪| 欧美一级一区| 国产波霸爆乳一区二区| 成人三级黄色| 大香蕉av在线| av电影在线观看| 俺也去视频| 欧洲一区在线观看| 99av| 久久久www成人免费毛片| 日日夜夜精品| 天天日天天操天天干| 91精品大屁股白浆自慰久久久| 麻豆成人网| 动漫一区二区三区| 成人一区二区电影| 天天干天天撸影视| 国产无码免费| 国产无码片| 国产足交| 免费在线黄色视频| japanese在线观看| 高清无码网站在线观看| 18禁裸体美女| 操逼无码| 免费在线观看A片| 国产黄色在线播放| 久久久无码视频| 国产成人精品一区二| 国产美女福利| 久久久精品中文字幕麻豆发布| 激情黄色毛片| 少妇456| 国产欧美一区二区| 亚洲艹| 免费看黄片,在线观看| 亚洲高清无码视频在线| 大香蕉这里只有精品| 中文字幕国产一区| 三级av网站| 阿拉伯三级片| 天天看天天干| 久久久久久久久久久高清毛片一级 | 国产高清无码免费| 日本少妇高潮| 伊人福利导航| 精品国产三级片| 亚洲AV无码精品国产| 青娱乐精品在线视频| 亚洲成人黄色视频| 天天射天天干天天| 久久久久久成人无码| 屁屁影院国产第一页| 日韩成人免费视频| 苍井空一区| 精品人妻一区| 国产午夜在线观看| 成人无码人妻| 一级一级一级做a免费一级做a| 91亚洲综合| 粉嫩99精品99久久久久| 免费黄网站在线观看| 91无码人妻东京热精品一区| 成人久操| 佐山爱人妻无码蜜桃| 国产成人宗合| 国产黄色电影| 手机看片福利| 大鸡巴导航| 黄片免费看| 四虎黄色网| 成人爽a毛片一区二区免费| 天堂在线无码| 亚洲人妻一区二区| 粉嫩99精品99久久久久久夜 | 深夜福利一区二区| 欧美日韩性色无码免费| 人人色人人黄| 日韩三区在线| 欧美日韩视频免费观看| 婷婷激情丁香五月天| 在线观看AV91| 人妻无码一二三区免费| 麻豆av人人乐| 国产香蕉视频| 黄色成人视频在线观看| 亚洲日韩精品中文字幕| 久久性| 91精品婷婷国产综合久久竹菊| 欧美综合国产| 毛片毛片毛片毛片| 超碰97人人操| 国产精品无码永久免费不卡| 91网站在线看| 粉粉嫩嫩的18虎白女| 国产香蕉在线| 宅男视频| 午夜神马福利| 黄色小视频免费观看| 北条麻妃无码视频在线观看| 99国产精品免费视频观看8| caopor在线| 国产高清无码一区二区| 成人性爱免费视频| 大香蕉在线伊| 中文字幕在线观看不卡| 婷婷五月影院| 中文字幕免费在线播放| 亚洲精品911| 欧美精品成人免码在线| 亚洲国产免费| 日韩成人A片| 国精品伦一区一区三区有限公司| 亚洲青青草| 欧美午夜网站| AV在线无码| 婷婷在线观看视频| 一级片无码| www.91久久| 先锋影音在线资源| 无码激情视频| 蜜桃视频在线观看18| 国产AV自拍-久| 国产嫩草久久久一二三久久免费观看 | 成年人黄色视频在线观看| 豆花视频免费观看| 黄色视频免费播放| 午夜无码影院| 在线免费观看AV片| 一级片在线免费观看| 91大片| 亚洲无码电影在线| 夜夜骚AV一二三区无码| 蜜桔视频嫩草蜜桃| 精品國產一區二區三區久久蜜月 | 婷婷亚洲精| 翔田千里无码流出两部| 日韩视频免费看| 欧美日韩一区二区三区四区五区六区 | 久久伊人大香蕉| 国产精品天天AVJ精麻传媒| 影音先锋中文字幕资源| 中文字幕码精品视频网站| 中文无码字幕视频| 亚洲AV无码高清| 99操逼视频| 美女A级毛片| 大炕上公让我高潮了六次| 国产成人精品一区二| 男女视频91| 无码人妻精品一区二区三区蜜臀百度 | 国精品无码一区二区三区在线| 热久久最新地址| 国产精品国产三级国产| 亚洲三级电影在线观看| 黄色视频网站在线看| 日韩AⅤ| 国产又爽又黄在线看视频| 在线中文av| 亚洲精品一区二区三区| 天天色天天| 中文字幕淫乱视频欧美| 亚洲国产av一区| 在线观看免费人成视频| 一级a一级a免费观看免免黄‘/ | 久久大香蕉| 欧美大香蕉伊人网| 91久久久久久久久| 欧美日韩高清丝袜| 成人做爰黄片视频免费| 人人摸人人操人人干| 婷婷五月丁香色| 一本高清无码| 97在线免费视频| 特级西西444www大胆免费看| 老妇性BBWBBWBBWBBW| 色射影院| 热久久最新地址| 日本国产欧美| 麻豆乱伦视频| 夜夜撸网站| 岛国无码在线观看| 亚洲中文字幕第一页| 国产黄色视频在线观看| 日本乱码视频| 欧美足交视频| 久久人人操人人| 蜜桃91精品入口| 亚洲AV成人无码精品直播在线| 日韩拍拍| 伊人网视频在线观看| 高清无码1区| 婷婷乱伦| 风间由美大荫蒂无码AV| 青青草无码在线| 永久免费av| 香蕉伊人在线| 亚洲福利| 亚洲日日干| 国产精品一区二区在线播放| 日韩日韩日韩日韩| 蜜桃网站在线观看| 亚洲在线视频播放| 日韩综合在线| 六月天av| 国产无码电影在线观看| www.三级片| 三级片在线网站| 9118禁| 亚洲天堂人妻少妇| 操逼操逼操逼操逼操逼操逼 | 91在线欧美| 骚网站在线观看| 四川婬妇BBw搡BBBB搡| 中文天堂网| 欧美怡春院| 国产精品视频瘾无码| 在线一区视频| 亚洲精选一区二区三区| 国产黄色视频免费| 91精品久久久久| 人人干人人操人人爽| AV电影在线免费观看| 尤物在线免费视频| 内射久久| 强伦轩一区二区三区四区播放方式 | 人妻超碰在线| 亚洲在线观看免费| 骚逼黄片| 北条麻妃无码视频在线观看| 国产精品福利在线| 99亚洲欲妇| 伊人成人免费视频| 五月色丁香| 青草91| 91成人片| 久草三级片| 人人操人人摸人人爽| 黑人狂躁女人高潮视频| 久视频在线| 亚洲第一狼人综合网| 日日摸日日添日日躁AV| 无码在线免费播放| 欧美丰满老熟妇XXXXX性| 五月激情视频| 黄色福利网址| 懂色av懂色av粉嫩av| 国产男女无套免费视频| 99er热精品视频| 中文字幕乱伦日本| AV国产精品| 成人久久久久一级大黄毛片中国 | www.色悠悠| 中文字幕第4页| 欧美黄片在线免费看| av在线天堂网| 欧美亚洲中文| av无码在线观看| 西西午夜视频| 日韩成人一级片| 人妻精品一区二区| 人人操人妻| 午夜偷拍网站| 伊人青青操| 日韩久久综合| 大香蕉啪啪| 人妻体体内射精一区二区| 91爱爱·com| 欧美黄色大片| 日韩小视频| www.91超碰在线| 啪啪网站免费观看| 日韩免费高清视频| 快播激情小说| 免费看毛片的网站| 97三级| 91成人做爰A片| 黄色毛片在线播放| 午夜福利小视频| 青青草大香蕉| 亚洲v欧美v| 婷婷五月中文| 亚洲AV成人精品日韩在线播放| 一区无码| 无码在线播| 亚洲国产激情视频| 国产秘久久一区二区| 国产美女18毛片水真多| 91人妻无码精品一区二区三区| 99九九久久| 欧美黄色大香蕉| 天天射天天日天天干| aaa久久| 天天操天天日天天干| 伊人五月丁香| 99视频精品全部免费看| 殴美老妇BBBBBBBBB| 日韩欧美日韩| ThePorn-成人网站入口| 日本亚洲欧美| 成人色色视频| 少妇喷水视频| 国产jk在线观看| 综合激情五月婷婷| 亚洲一级性爱| 日韩精品久久| 欧美A片免费观看| aaa国产| 久草综合视频| 日韩v欧美v日本v亚洲v国产v| 在线无码免费视频| 在线操| 日韩免费在线观看| 2025AV在线| 免费在线观看黄色视频| 一道本激情视频| 亚洲激情五月| 亚洲精品影院| 国产超级无码高清在线视频观看| 五月天婷婷激情网| 久久亚洲视频| 成人毛片一区二区三区无码| 成人做爰A片免费看网站| 久久久国产视频| 翔田千里无码免费播放| 亚洲国产婷婷香蕉A片| 91大神免费观看| 荫蒂添到高潮免费视频| 青青草原在线| 中文字幕免费看高清| 国产欧美岛国| 欧美久久久久| 52妺嘿嘿午夜福利在线| 操逼福利视频|