PIL:處理圖像的好模塊

介紹

PIL是一個專門用來處理圖像的模塊,能夠對圖象進行各類各樣的變換

打開一張圖片

from PIL import Image

# 調用Image下的open方法,便可打開一張圖片
# 獲得的im即是圖片的字節流
# 咱們即可以對im進行操做
im = Image.open("古明地覺.jpg")

查看圖片的相關信息

  • 顯示圖片python

    im.show()

  • 獲取圖片的信息git

    print(im.format)  # JPEG
  • 獲取大小算法

    print(im.size)  # (960, 626)
    """
    關於圖片的大小,我要說兩句
    
    首先圖片的結構是一個三維數組,第一維表示行,第二維表示列,第三位表示rgb或者灰度值
    咱們日常說一張圖片是1920*1080,指的是這張圖片每一行有1920個像素,每一列有1080個像素,想成一個長方形的話,就是長爲1920,寬爲1980
    每個像素點,是一個rgb或者灰度值,全部的像素組合,成爲一張圖片
    
    1920 * 1080至關因而有1080行,1920列
    通常咱們對數組進行操做時,好比numpy,經過指定在哪一行、以及哪一列來獲取對應的元素。都是先肯定行,而後再肯定列
    
    好比對於這樣一張1920*1080的圖片,假設轉爲了一個numpy裏面的數組。我若是要獲取圖片最右下角的那一個點的像素值的話,我要怎麼獲取呢?
    是arr[1080, 1920],仍是[1920, 1080]呢?
    答案顯然是前者,由於數組會先肯定行,而後再肯定列
    
    1920*1080表示有1080行,1920列,因此是arr[1080, 1920]。
    若是是arr[1920, 1080]的話,顯然長度越界了
    
    這裏的圖片size是(960, 626),表示圖片的長是960個像素,寬626個像素。對應數組則是,626行,960列
    """
  • 查看圖片的直方圖api

    print(im.histogram())
    """
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 2, 4, 5, 5, 5, 5, 5, 9, 15, 27, 25, 24, 
    30, 30, 47, 67, 78, 96, 130, 133, 164, 182, 178, 205, 260, 281, 275, 250, 252, 238, 268, 258, 259, 265, 294, 
    286, 277, 307, 333, 316, 360, 317, 393, 376, 453, 441, 449, 467, 503, 526, 529, 642, 589, 611, 624, 729, 827, 
    975, 2728, 1204, 984, 993, 933, 1072, 769, 679, 629, 680, 655, 631, 607, 543, 562, 587, 561, 576, 577, 572, 576, 
    563, 579, 550, 547, 530, 564, 554, 530, 505, 560, 581, 581, 569, 552, 554, 572, 579, 583, 578, 555, 580, 590, 579, 
    566, 635, 604, 641, 611, 632, 673, 609, 608, 642, 630, 652, 594, 651, 685, 632, 688, 721, 696, 708, 720, 738, 682, 
    722, 742, 694, 762, 753, 797, 813, 777, 814, 1039, 1134, 1336, 1149, 1395, 1469, 1252, 1276, 1190, 1114, 1234, 1178, 
    1249, 1200, 1188, 1231, 1305, 1177, 1234, 1336, 1436, 1481, 1444, 1470, 1445, 1548, 1440, 1480, 1362, 1492, 1482, 
    1487, 1458, 1503, 1493, 1591, 1380, 1417, 1547, 1549, 1532, 1480, 1629, 1685, 1650, 1576, 1693, 1736, 1849, 2003, 
    2013, 2240, 2443, 2911, 4315, 3522, 17555, 3966, 2752, 2639, 2498, 2492, 2525, 2649, 2691, 2686, 3173, 3578, 3950, 
    3769, 3993, 4172, 4318, 4135, 4503, 4561, 4732, 5195, 5465, 5763, 6722, 8012, 7917, 9095, 9090, 9263, 10565, 17944, 
    15564, 33561, 14438, 18056, 14119, 10557, 8824, 8699, 11656, 24911, 102089, 37, 10, 16, 17, 20, 29, 39, 30, 55, 53, 
    69, 84, 97, 95, 129, 156, 184, 225, 251, 310, 336, 390, 392, 441, 496, 543, 611, 678, 634, 517, 556, 526, 492, 520, 
    571, 561, 618, 554, 582, 603, 609, 591, 627, 651, 643, 709, 652, 693, 644, 679, 676, 694, 636, 663, 732, 687, 774, 
    858, 928, 1130, 2931, 1386, 1231, 1123, 1075, 1201, 931, 805, 713, 704, 691, 666, 654, 625, 624, 618, 617, 693, 612, 
    587, 583, 574, 574, 538, 525, 576, 590, 616, 585, 583, 580, 595, 625, 636, 633, 588, 647, 663, 647, 652, 666, 696, 725, 
    710, 720, 784, 795, 810, 845, 815, 864, 882, 895, 850, 810, 828, 807, 864, 794, 798, 811, 824, 773, 850, 847, 848, 861, 
    947, 980, 988, 939, 1031, 1005, 1059, 1022, 1155, 1159, 1167, 1240, 1293, 1282, 1212, 1293, 1295, 1402, 1351, 1430, 
    1376, 1422, 1412, 1544, 1493, 1376, 1459, 1401, 1458, 1360, 1468, 1497, 1544, 1695, 1815, 1824, 1789, 1837, 1830, 1822, 
    1993, 2035, 2089, 1977, 2045, 2068, 2208, 2347, 2436, 2372, 2407, 2331, 2644, 2881, 2796, 2746, 2870, 2757, 2658, 2650, 
    2829, 2937, 2806, 2939, 3343, 3467, 3558, 3596, 3741, 3821, 5841, 4104, 3709, 3868, 3707, 4067, 4130, 4181, 4412, 4429, 
    4207, 4193, 4245, 4349, 5025, 5866, 8310, 23939, 6447, 5139, 4911, 4898, 5203, 5157, 6506, 6787, 6445, 7493, 14253, 
    8702, 8904, 6328, 7212, 6623, 7041, 5137, 3894, 4669, 4247, 4305, 10851, 7108, 13967, 15077, 23766, 17083, 5750, 8382, 
    18893, 3736, 3179, 8640, 3894, 890, 511, 345, 303, 238, 373, 24, 3, 3, 6, 13, 7, 9, 14, 12, 24, 28, 28, 35, 40, 40, 53, 
    67, 75, 87, 104, 122, 134, 208, 225, 269, 286, 303, 349, 351, 391, 404, 453, 486, 524, 583, 505, 601, 544, 587, 615, 
    533, 554, 485, 522, 570, 560, 586, 579, 568, 639, 636, 622, 638, 746, 754, 948, 962, 2379, 1296, 1546, 1255, 1210, 
    1318, 913, 809, 750, 797, 707, 663, 671, 639, 616, 599, 650, 655, 643, 647, 616, 619, 657, 679, 646, 585, 686, 626, 
    630, 659, 626, 642, 603, 634, 643, 645, 589, 633, 601, 691, 627, 626, 665, 641, 656, 664, 668, 644, 615, 696, 690, 
    705, 743, 782, 813, 731, 798, 834, 817, 826, 831, 842, 881, 924, 884, 977, 996, 997, 1002, 1015, 1015, 960, 1062, 1061, 
    1019, 1028, 990, 1065, 1002, 1043, 1071, 1013, 1059, 1047, 1046, 1108, 1118, 1102, 1064, 1170, 1140, 1265, 1355, 1394, 
    1388, 1361, 1456, 1433, 1597, 1616, 1787, 1779, 1909, 1967, 1904, 2134, 2437, 2444, 2982, 2686, 2675, 2575, 2609, 2597, 
    2667, 2536, 2445, 2588, 2651, 2943, 2946, 2885, 2726, 2733, 2807, 2994, 3399, 3602, 3712, 3730, 3513, 3914, 3909, 4060, 
    4119, 4199, 4356, 4291, 4224, 4264, 4537, 4651, 4894, 5129, 5498, 5929, 6614, 9097, 7885, 8448, 8050, 8585, 9255, 12108, 
    15453, 10869, 16029, 10879, 13984, 16131, 36720, 8793, 10447, 9403, 4410, 14121, 8540, 14786, 11199, 2803, 2821, 1814, 
    1805, 1879, 1461, 1457, 1504, 1420, 1673, 1515, 1541, 1616, 1852, 2186, 2468, 5031, 7030, 15774, 2499, 2253, 1463, 922,
    738, 611, 487, 323, 417, 214, 616]
    
    """

im(圖片字節流)的一些操做

  • 獲取某一個像素數組

    # 以前咱們說先按照行,再按照列獲取像素點。
    # 可是在im.getpixel裏面是按照列和行來的,由於這樣符合咱們的平常思惟,可是有的就不是
    # 因此有時候是按照行和列,仍是列和行,容易混淆,就很煩
    # 這裏則是獲取長度爲第850、寬爲第300個像素,以元組的形式傳入。咱們這裏是彩色圖片,因此會返回一個三元組
    print(im.getpixel((850, 300)))  # (246, 214, 215)
    # 此外獲取還有一種辦法
    pixel = im.load()
    print(pixel[850, 300])  # (246, 214, 215)
    # 而且下面的方法會更快一些
  • 修改某個像素的顏色緩存

    # 這裏第一個參數是像素的位置,依舊是列和行的順序
    # 第二個參數是rgb三元組
    for i in range(im.size[1]):
        im.putpixel((i, i), (100, 100, 100))
    
    im.show()
    # 或者
    """
    pixel = im.load()
    for i in range(im.size[1]):
        pixel[i, i] = (100, 100, 100)
    im.show()
    """
    # 下面這種方式會更快一些

    注意到圖片上有一個斜線,就是咱們對像素進行修改的結果。所以修改像素是在本地進行操做的,直接影響im,進而影響im.show()所顯示的圖片網絡

    另外值得一提的是,我這裏的代碼省略了一部分,不是一次性執行的,而是反覆執行了。爲了簡潔,我把以下代碼省略了dom

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")

    所以每次執行都會從新加載圖片,從新獲得一個im對象函數

  • 圖片縮放post

    # 縮放爲原來的1/2
    im1 = im.resize((im.size[0] // 2, im.size[1] // 2))
    im1.show()

    此外還有一種縮放圖片的方式,im.thumbnail,這個和resize不一樣,resize是返回一個新的對象,thumbnail則是在原來對象的基礎上進行修改,因此能夠先copy一下

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    im1 = im.copy()
    # 縮放爲原來的1/2
    im1.thumbnail((im.size[0] // 2, im.size[1] // 2))
    im1.show()

  • 圖像翻轉

    # 填入角度,按照逆時針進行翻轉
    im1 = im.rotate(90)
    im1.show()

  • 圖像的裁剪與粘貼

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    # 先獲取一個矩形區域,傳入矩形的左上頂點和右下頂點兩個座標
    # 這樣就能定位一個矩形
    box = (120, 194, 220, 294)
    
    # 裁剪,而後旋轉九十度,獲得的還是一個Image對象
    region = im.crop(box).rotate(90)
    
    # 粘貼,傳入兩個參數,Image對象,位置
    im.paste(region, box)
    
    # 這個不會返回新的對象,直接在本地修改
    im.show()

  • 圖像通道的分離

    彩色圖像有三個通道,能夠對通道進行分離,獲得三個通道分別對應的圖像,此時每一個圖像只有一個份量。注意:分離的以後,獲得的還是Image對象

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    r, g, b = im.split()
    print(r)  # <PIL.Image.Image image mode=L size=960x626 at 0x1EB4768B048>
    print(g)  # <PIL.Image.Image image mode=L size=960x626 at 0x1EB4768BF60>
    print(b)  # <PIL.Image.Image image mode=L size=960x626 at 0x1EB47697320>
    
    r.show()
    g.show()
    b.show()

  • 圖像的點運算

    能夠實現總體變亮或者變暗的效果

    im1 = im.point(lambda x: x * 1.8)
    im1.show()
    
    im2 = im.point(lambda x: x * 0.6)
    im2.show()

  • 將圖片轉化爲灰度圖片

    im1 = im.convert("L")
    im1.show()

    這和im.split轉化爲單通道有點像



圖像過濾

可使用ImageFilter來對圖像進行細節上的加強、變換等等,固然仍是對im進行操做,可是參數主要是ImageFilter這個模塊提供的。這個模塊提供不少的過濾器,經過指定不一樣的過濾器參數,來對圖片進行不一樣的變換

from PIL import Image
from PIL import ImageFilter

im = Image.open("古明地覺.jpg")
  • 圖像模糊

    # 圖像模糊
    im1 = im.filter(ImageFilter.BLUR)
    im1.show()

  • 圖像加強(細節突出)

    im1 = im.filter(ImageFilter.DETAIL)
    im1.show()

  • 圖像邊緣提取

    im1 = im.filter(ImageFilter.FIND_EDGES)
    im1.show()

  • 圖像輪廓

    im1 = im.filter(ImageFilter.CONTOUR)
    im1.show()

  • 邊緣加強濾波

    加強不一樣灰度之間的邊界和輪廓

    im1 = im.filter(ImageFilter.EDGE_ENHANCE)
    im1.show()
    
    # 從名字也能看出來,做用同樣,可是效果加強了
    im2 = im.filter(ImageFilter.EDGE_ENHANCE_MORE)
    im2.show()

  • 浮雕效果

    im1 = im.filter(ImageFilter.EMBOSS)
    im1.show()

  • 平滑濾波

    突出圖像的主幹部分,減小突變

    im1 = im.filter(ImageFilter.SMOOTH)
    im1.show()
    
    im2 = im.filter(ImageFilter.SMOOTH_MORE)
    im2.show()

  • 銳化

    im1 = im.filter(ImageFilter.SHARPEN)
    im1.show()


圖像過濾(高級用法)

  • ImageFilter.Kernel(size, kernel, scale=None, offset=0)

    有點相似於TensorFlow裏的卷積神經網絡
    size:卷積核的尺寸,好比爲(3, 3)或者(5, 5)
    kernel:size爲(3, 3),那麼kernel必須爲由9個int或者float組成的元組。若是size爲(5, 5),那麼kernel爲25個
    scale:若是設置了,那麼卷積核做用每一個像素以後都要除以scale,默認是卷積核的權重之和
    offset:卷積核做用於每一個像素以後要加上offset再除以scale,默認是0
    im1 = im.filter(ImageFilter.Kernel((3, 3), (1, 1, 1, 0, 1, 0, 1, 0, 1), scale=None, offset=0))
    im1.show()

  • ImageFilter.RankFilter(size, rank)

    生成等級濾波器,對於每個像素點,等級濾波器根據像素值,在(size, size)的區域中對全部像素點進行排序,而後將對應等級的值拷貝到圖像中。rank∈[0, size * size -1],size * size * 0.5爲中等
    # 表示在每一個像素點爲中心的3*3區域組成的9個像素中,選擇第7位的像素做爲新值
    im1 = im.filter(ImageFilter.RankFilter(3, 7))
    im1.show()

    感受有點相似模糊的效果

  • ImageFilter.MinFilter(size)

    和RankFilter相似,不過只須要指定一個size便可,會自動選擇最小的,至關於rank=0

    im1 = im.filter(ImageFilter.MinFilter(3))
    im1.show()

  • ImageFilter.MaxFilter(size)

    和上一次同樣,只不過是選取最大的

    im1 = im.filter(ImageFilter.MaxFilter(3))
    im1.show()

  • ImageFilter.MedianFilter(size)

    選取中間的

    im1 = im.filter(ImageFilter.MedianFilter(3))
    im1.show()

  • ImageFilter.ModeFilter(size)

    選擇(size, size)中出現次數最多的像素值,若是沒有出現兩次或者兩次以上的,就用原始的像素值

    im1 = im.filter(ImageFilter.ModeFilter(3))
    im1.show()
    
    im2 = im.filter(ImageFilter.ModeFilter(6))
    im2.show()

    size=3還能夠,等於6就有點



Image模塊下的api


  • Image.eval

    相似於im.point,這個函數會有一個返回值,不會在原來的圖像上進行操做

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    # 接收兩個參數,Image對象,和函數
    im1 = Image.eval(im, lambda x: x * 0.5)
    im1.show()

  • Image.blend

    圖像融合,使用兩張圖像和一個透明度,融合成一張新的圖像。注意:融合的時候,兩張圖像的尺寸必需要相同

    from PIL import Image
    
    im1 = Image.open("古明地覺.jpg").resize((600, 400))
    im2 = Image.open("古明地戀.jpg").resize((600, 400))
    
    im1.show()
    im2.show()

    from PIL import Image
    
    im1 = Image.open("古明地覺.jpg").resize((600, 400))
    im2 = Image.open("古明地戀.jpg").resize((600, 400))
    
    """
    參數1:圖像1
    參數2:圖像2
    參數3:透明度alpha
    合成公式:圖像1 * (1 - alpha) + 圖像2 * alpha
    能夠看出,若是alpha=0,那麼結果就是圖像1,alpha=1,結果就是圖像2 
    """
    im = Image.blend(im1=im1, im2=im2, alpha=0.6)
    im.show()

  • Image.composite

    將兩張圖片進行合成,和blend相似

    from PIL import Image
    
    im1 = Image.open("古明地覺.jpg").resize((600, 400))
    im2 = Image.open("古明地戀.jpg").resize((600, 400))
    
    """
    參數1:圖像1
    參數2:圖像2
    參數3:mask,圖像的一個通道。這是再也不是透明度alpha
    """
    im = Image.composite(image1=im1, image2=im2, mask=im1.split()[1])
    im.show()

  • Image.merge

    這個方法和split是對應的,split是將圖片的三個通道進行分解,而merge是將三個通道進行融合,相似於pandas裏面的merge

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    r, g, b = im.split()
    
    # 獲得的r、g、b均是Image對象,因此可使用對象的全部方法
    r = r.point(lambda x: x * 1.3)  # r通道變爲原來的1.3倍
    g = g.point(lambda x: x * 0.9)  # g通道變爲原來的0.9倍
    b = b.point(lambda x: 0)  # g通道變爲0
    
    # 融合
    # 接收兩個參數
    # 參數一:模式,這裏直接使用原圖的模式
    # 參數二:三通道,要以元組的方式傳入
    print(im.mode)  # RGB
    im1 = Image.merge(im.mode, (r, g, b))
    
    im1.show()

    獲得了一個暖色調的圖像

  • 讀取gif格式的圖片

    # 此外,Image.open()還能夠讀取gif格式
    '''
    im = Image.open("xxx.gif")
    # 從序列中查找指定的幀,若是越界會拋出一個EOFError異常
    # 當文件序列被打開,自動獲取第零幀
    # 這裏顯示第二幀
    im.seek(2).show()
    
    # 獲取當前幀所處的位置,從0開始計算
    im.tell()
    '''


圖片的變換

這裏的方法是經過im對象調用的

im.transform

圖像能夠有大小或者形狀上的變化。
主要是用im.transform(size, method, data, filter)
size:新圖像的尺寸
method:有EXTENT(裁剪一個矩形區域),AFFINE(仿射變換),QUAD等等,下面舉例介紹
data:裁剪的區域,傳入矩形的左上頂點和右下頂點
filter:濾波器,有NEAREST,BILINEAR,BICUBIC,ANTIALIAS。中間兩個不經常使用,NEAREST速度最快,ANTIALIAS質量最高
  • ENTENT

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    """
    表示將im的(0, 0, 600, 600)這塊區域裁剪出來,而且尺寸變爲(300, 300)
    咱們裁剪的區域的寬和高爲600和600,那麼在變換的時候也要符合比例,否則會有拉伸和壓縮
    至於濾波器咱們不用管,默認的就好
    
    這種方法相似於im.crop可是速度上沒有crop塊,速度上相似於resize
    這個方法是有返回值的
    """
    im1 = im.transform((300, 300), Image.EXTENT, (0, 0, 600, 600))
    im1.show()

  • AFFINE

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    """
    前兩個參數不用說,關鍵是第三個參數
    傳入一個元組(a, b, c, d, e, f)那麼原來的(x, y)就會被映射成(ax+by+c, dx+ey+f)
    """
    im1 = im.transform((300, 300), Image.AFFINE, (1, 2, 1, 2, 1, 3))
    im1.show()

  • QUAD

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    """
    這個簡單,就是輸出圖像的一個四邊形
    這裏是圖像的截取部分,須要傳入左上、左下、右下、右上四個位置,我的以爲只須要傳兩個就能夠了
    """
    im1 = im.transform((300, 300), Image.QUAD, (0, 0, 0, 400, 500, 400, 500, 0))
    im1.show()

  • PERSPECTIVE

    from PIL import Image
    
    im = Image.open("古明地覺.jpg")
    
    """
    透視變化
    和仿射相似,只不過最後一個元組須要傳入8個值
    (a, b, c, d, e, f, g, h),而後(x, y)會映射成( (ax+by+c)//(gx+hy+1), (dx+ey+f)//(gx+hy+1) )
    """
    im1 = im.transform((300, 300), Image.PERSPECTIVE, (1, 1, 1, 1, 0, 0, 0, 0))
    im1.show()

im.transpose

能夠對圖像進行翻轉

from PIL import Image

im = Image.open("古明地覺.jpg")


im1 = im.transpose(Image.FLIP_LEFT_RIGHT)  # 左右翻轉
im2 = im.transpose(Image.FLIP_TOP_BOTTOM)  # 上下翻轉
im1.show()
im2.show()



圖像加強

PIL還提供了了一個專門用來加強圖像的模塊,叫ImageEnhance

操做也很簡單
調用ImageEnhance下的某個方法,傳入Image對象,也就是im,獲得一個加強圖像的對象,好比叫enh
而後調用enh.enhance方法,傳入加強或者減弱的數值,變獲得一個新的Image對象,能夠直接調用show方法,或者Image.open()獲得的對象的其餘方法
from PIL import Image, ImageEnhance

im = Image.open("古明地覺.jpg")

# 傳入Image對象im,獲得能夠操做亮度的對象
enh = ImageEnhance.Brightness(im)

# 加強或者減弱亮度
enh.enhance(1.5).show()  # 加強爲原來的1.5倍
enh.enhance(0.3).show()  # 減弱爲原來的0.3倍

from PIL import Image, ImageEnhance

im = Image.open("古明地覺.jpg")

# 傳入Image對象im,獲得能夠操做對比度的對象
enh = ImageEnhance.Contrast(im)

# 加強或者減弱對比度
enh.enhance(1.5).show()  # 加強爲原來的1.5倍
enh.enhance(0.3).show()  # 減弱爲原來的0.3倍

from PIL import Image, ImageEnhance

im = Image.open("古明地覺.jpg")

# 傳入Image對象im,獲得能夠操做銳化的對象
enh = ImageEnhance.Sharpness(im)

# 加強或者減弱銳化
enh.enhance(20).show()  # 加強爲原來的20倍
enh.enhance(0.5).show()  # 減弱爲原來的0.5倍

from PIL import Image, ImageEnhance

im = Image.open("古明地覺.jpg")

# 傳入Image對象im,獲得能夠操做顏色均衡的對象
enh = ImageEnhance.Color(im)

# 加強或者減弱顏色均衡
enh.enhance(5).show()  # 加強爲原來的5倍
enh.enhance(0.5).show()  # 減弱爲原來的0.5倍



圖像加特技

PIL還爲咱們提供了ImageChops模塊(channel operations),能夠對圖像進行一些特效上的操做。

  • ImageChops.constant(image, value)

    返回一個和image大小同樣,像素值爲value的層

    from PIL import Image, ImageChops
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageChops.constant(im, 200)
    im1.show()

  • ImageChops.dupicate(image)

    返回給定圖像的拷貝,相似於im.copy()

    from PIL import Image, ImageChops
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageChops.duplicate(im)
    im1.show()

  • ImageChops.invert(image)

    返回一個新圖像,新圖像的每個像素等於255-原像素

    from PIL import Image, ImageChops
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageChops.invert(im)
    im1.show()

  • ImageChops.lighter(image1, image2)

    將兩個圖片的像素逐個比較,選取較大的做爲新圖片的像素,二者尺寸能夠不同,尺寸至關於會取二者共有的部分。若是是600*400和700*300,那麼獲得結果會是600*300

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg")
    im2 = Image.open("古明地戀.jpg")
    
    im = ImageChops.lighter(im1, im2)
    im1.show()
    im2.show()
    im.show()

  • ImageChops.darker(image1, image2)

    從名字也能看出,選取較小的做爲新像素

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg")
    im2 = Image.open("古明地戀.jpg")
    
    im = ImageChops.darker(im1, im2)
    im.show()

  • ImageChops.difference(image1, image2)

    返回兩個圖片像素的絕對差值做爲新圖片的像素

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg")
    im2 = Image.open("古明地戀.jpg")
    
    im = ImageChops.difference(im1, im2)
    im.show()

  • ImageChops.mutiply(image1, image2)

    兩張圖片進行融合,image1 * image2 / MAX,對應像素相乘,而後除以較大的像素

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg")
    im2 = Image.open("古明地戀.jpg")
    
    im = ImageChops.multiply(im1, im2)
    im.show()

  • ImageChops.screen(image1, image2)

    將兩張圖片進行融合,這幾個api比較相似,無非是像素的算法不同,result = MAX -((MAX - image1) * (MAX - image2) / MAX)

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg")
    im2 = Image.open("古明地戀.jpg")
    
    im = ImageChops.screen(im1, im2)
    im.show()

  • ImageChops.add(image1, image2, scale, offset)

    result = (image1 + image2)/scale + offset

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg")
    im2 = Image.open("古明地戀.jpg")
    
    im = ImageChops.add(im1, im2)
    im.show()
    
    im = ImageChops.add(im1, im2, 5)
    im.show()

  • ImageChops.subtract(image1, image2, scale, offset)

    result = (image1 - image2) / scale + offset

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg")
    im2 = Image.open("古明地戀.jpg")
    
    im = ImageChops.subtract(im1, im2)
    im.show()
    
    im = ImageChops.subtract(im1, im2, 5)
    im.show()

  • ImageChops.blend(image1, image2, alpha)

    和Iamge模塊的blend用法同樣,將兩張圖像合併爲一張,注意:此時要求圖片尺寸一致

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg").resize((600, 400))
    im2 = Image.open("古明地戀.jpg").resize((600, 400))
    
    im = ImageChops.blend(im1, im2, 0.5)
    im.show()

  • ImageChops.composite(image1, image2, mask)

    根據mask合成兩張圖像,mask能夠是一個通道,和Image下的composite是同樣的。同理,要求兩張圖片尺寸一致

    from PIL import Image, ImageChops
    
    im1 = Image.open("古明地覺.jpg").resize((600, 400))
    im2 = Image.open("古明地戀.jpg").resize((600, 400))
    
    im = ImageChops.composite(im1, im2, im1.split()[0])
    im.show()
    
    im = ImageChops.composite(im1, im2, im1.split()[1])
    im.show()

  • ImageChops.offset(image, xoffset, yoffset)

    原圖像(x,y)--》新圖像(x+xoffset, y+yoffset)

    from PIL import Image, ImageChops
    
    im = Image.open("古明地覺.jpg")
    im1 = ImageChops.offset(im, 100, 200)
    im1.show()



圖像處理

PIL還提供了一個ImageOps模塊,包含一些圖像處理操做

  • ImageOps.autocontrast(image, cutoff=0)

    最大圖像對比度。計算一個輸入圖像的直方圖,image.histogram(),除去最亮和最暗的百分之cutoff,從新映射圖像

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    im1 = ImageOps.autocontrast(im, 15)
    im1.show()

  • ImageOps.colorize(image, black, white)

    使得灰色圖像變爲彩色圖像,變量black和white應該是RGB元組或者顏色名稱。這個函數會使得原圖像的全部黑色變成black,全部白色變成white,前提是變量image的模式必須爲L,使用im.split()會獲取三個通道,那麼每一個通道的模式便爲L

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg").convert("L")
    
    im1 = ImageOps.colorize(im, "pink", "green")
    im1.show()

  • ImageOps.crop(image, border=0)

    相似於im.crop(),可是參數不太同樣,那個border依舊是一個元組,包含四個int。但不是矩形的左上和右下頂點,而是表示左上右下分別去掉多少行/列

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    # 表示左邊去掉200列,上邊去掉100行,右邊去掉300列,下邊去掉200行
    im1 = ImageOps.crop(im, border=(200, 100, 300, 200))
    im1.show()

  • ImageOps.equalize(image)

    產生一個灰色值均勻分佈的圖像

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.equalize(im)
    im1.show()

  • ImageOps.expand(image, border=0, fill=0)

    和crop相反,expand表示擴充行/列,用fill指定的顏色填充

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.expand(im, border=(100, 100, 100, 100), fill="pink")
    im1.show()

  • ImageOps.fit(image, size, method, bleed, centering)

    size:輸出的尺寸
    method:採樣的方法,默認是NEARST,速度最快
    bleed:去除邊界(四個),須要傳入一個百分比,如0.01,去除百分之一的邊界。默認是0
    centering:裁剪位置,(0.5,0.5)表示中心,(0, 0),左上角,(1.0, 0)左下角。(1.0, 1.0)右下角
               (0.5,0.5),裁剪寬度,從右邊開始,裁剪高度,從底部開始
               (0,0),裁剪寬度,從右邊開始,裁剪高度,從底部開始
               (1.0,0),裁剪寬度,從左邊開始,裁剪高度,從底部開始
    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.fit(im, (400, 400), Image.NEAREST, 0.3, (1.0, 0))
    im1.show()

  • ImageOps.flip(image)

    輸出image在垂直方向的景象

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.flip(im)
    im1.show()

  • ImageOps.mirror(image)

    既然有垂直方向的景象,那就確定有水平方向上的

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.mirror(im)
    im1.show()

  • ImageOps.grayscale(image)

    將彩色圖像轉化爲灰度圖像

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.grayscale(im)
    im1.show()

  • ImageOps.invert(image)

    每個像素都用255去減,和ImageChops.invert()功能同樣

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.invert(im)
    im1.show()

  • ImageOps.posterize(image,bits)

    將每一個顏色通道值的低bits個位設置爲0

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.posterize(im, 10)
    im1.show()

  • ImageOps.solarize(image,threshold=128)

    在指定的閾值範圍內,翻轉全部的像素點

    from PIL import Image, ImageOps
    
    im = Image.open("古明地覺.jpg")
    
    im1 = ImageOps.solarize(im, threshold=128)
    im1.show()



ImageDraw

ImageDraw是PIL裏面的一個畫筆,咱們能夠導入圖像,也能夠繪製圖像。既然要繪製圖像,那麼確定要有畫筆啊。調用ImageDraw模塊下的Draw方法,draw=ImageDraw(im),傳入的im也就是Image對象,就能夠生成一個畫筆,那麼畫筆所畫的內容就會顯示在im(畫板)上。那麼這個畫板能夠是image.open建立的Image對象,也能夠是本身建立的Image對象。下面咱們就來本身建立


建立一個畫板

from PIL import Image

"""
三個參數:
第一個參數:模式
第二個參數:畫板的長和寬
第三個參數:畫板的顏色,是一個三元組
"""
im = Image.new("RGB", (200, 80), (150, 155, 180))
im.show()

建立畫筆

from PIL import Image
from PIL import ImageDraw

im = Image.new("RGB", (200, 80), (150, 155, 180))
# 此時變獲得一個畫筆,畫筆所畫的內容都會顯示在im上面
draw = ImageDraw.Draw(im)

繪製直線

from PIL import Image
from PIL import ImageDraw

im = Image.new("RGB", (200, 80), (150, 155, 180))
draw = ImageDraw.Draw(im)
"""
line方法表示畫一條直線,參數以下:
參數一:起點和終點位置,[x1, y1, x2, y2]
參數二:fill,用什麼顏色填充,是一個rgb三元組
參數三:width:線條寬度
"""
draw.line([10, 10, 150, 80], fill=(150, 140, 255), width=2)
draw.line([20, 10, 50, 180], fill=(250, 40, 155), width=2)

im.show()

繪製曲線

from PIL import Image
from PIL import ImageDraw

im = Image.new("RGB", (800, 600), (100, 100, 100))
draw = ImageDraw.Draw(im)
"""
和繪製直線相似,可是座標的意義不同

參數一:起點和終點位置,和直線不同,直線是兩點肯定一條直線,而曲線裏的起點和終點,表示一個矩形的左上頂點和右下頂點
參數二:起始角度
參數三:終止角度

而後會根據參數一獲得的矩形畫出一個與矩形四邊都想切的圓
而後根據起始角度和終止角度從滿圓中截取相應的弧
而且規定相應矩形的水平中位線爲零度角,而後順時針變大

參數四:fill,填充顏色,rgb三元組,或者顏色名
參數五:width,線條寬度
"""
draw.arc([0, 0, 600, 400], 0, 360, fill="blue", width=2)
"""
若是矩形跑到了畫板的外面,仍然會按照相應的規則畫圓,截取
就僞裝有畫板,只是顯示的時候超出畫板的部分不顯示
有時候咱們想畫出一條曲線的時候,即可以採用這種辦法
經過畫圓的方式,而後截取一部分弧
"""
draw.arc([-100, -100, 1000, 200], 0, 360, fill="red", width=2)
im.show()

繪製圓或者橢圓

這個和上面的arc相似,其實arc也算是用來畫圓的

from PIL import Image
from PIL import ImageDraw

im = Image.new("RGB", (800, 600), (100, 100, 100))
draw = ImageDraw.Draw(im)

"""
參數一:和arc的第一個參數是同樣的
此時不須要起始和終止角度了,由於畫的就是圓或者橢圓

參數二:fill,填充色,圓或者橢圓內部的顏色
參數三:outline,輪廓的顏色
參數四:width,線條的寬度
"""
draw.ellipse([100, 100, 600, 600], fill="blue")
draw.ellipse([100, 100, 500, 300], outline="red", width=2)
im.show()

draw.chord

用法和arc相似,只不過fill變成填充色,arc中的表示輪廓的fill在arc裏面成爲了outline

from PIL import Image
from PIL import ImageDraw

im = Image.new("RGB", (800, 600), (100, 100, 100))
draw = ImageDraw.Draw(im)

draw.chord([0, 0, 600, 400], 0, 360, fill="blue", width=2)

draw.arc([-100, -100, 1000, 200], 0, 360, fill="red", width=2)
im.show()

繪製扇形

參數和chord同樣

from PIL import Image
from PIL import ImageDraw

im = Image.new("RGB", (800, 600), (100, 100, 100))
draw = ImageDraw.Draw(im)

draw.pieslice([100, 100, 600, 600], 0, 90, fill="cyan", width=3)

im.show()

繪製多邊形

傳入相應點的座標,會將多個點依次相連

from PIL import Image
from PIL import ImageDraw

im = Image.new("RGB", (800, 600), (100, 100, 100))
draw = ImageDraw.Draw(im)

draw.polygon([(50, 60), (100, 100), (150, 50), (250, 600), (50, 60)], fill="cyan", outline="green")

im.show()

繪製矩形

from PIL import Image
from PIL import ImageDraw

im = Image.new("RGB", (800, 600), (100, 100, 100))
draw = ImageDraw.Draw(im)

draw.rectangle([100, 100, 400, 400], outline="green")
draw.rectangle([200, 200, 300, 300], fill="blue")

im.show()

字體對象

既然要畫,確定要有字體啊

from PIL import Image
from PIL import ImageFont

im = Image.new("RGB", (800, 600), (100, 100, 100))
"""
參數一:字體
參數二:大小,size
參數三:index,有的字體是一系列字體的組合index表示用第幾個,通常不指定
"""
font = ImageFont.truetype(r"C:\Windows\Fonts\msth.ttc", 40)

繪製文字

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw

im = Image.new("RGB", (800, 600), "cyan")
draw = ImageDraw.Draw(im)
font = ImageFont.truetype(r"C:\Windows\Fonts\simkai.ttf", 40)

"""
使用text方法繪製文字
參數一:起始位置
參數二:文字,text
參數三:font,字體對象,若是不指定,則使用默認字體
參數四:fill,字體的填充顏色
"""
draw.text([100, 200], text="古明地覺最可愛", font=font, fill=(100, 185, 179))
im.show()


手動生成驗證碼

繪製噪點

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import random
import string

# 隨機生成一個畫板顏色
bg_color = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
# 定義畫板的寬和高
width, height = 200, 80

# 建立畫板
im = Image.new("RGB", (width, height), bg_color)

# 建立畫筆對象,接收畫板對象,這樣一來,畫筆所畫的內容都會顯示在畫板上。
draw = ImageDraw.Draw(im)

# 繪製噪點,不要過多,通常爲寬乘高再乘以0.1
for _ in range(int(width * height * 0.1)):
    # 噪點的橫縱座標
    x_y_point = random.randint(0, width), random.randint(0, height)
    # 填充色,儘可能隨機
    fill = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
    # 繪製
    draw.point(x_y_point, fill)
    
# 先來看看畫板長啥樣
im.show()

能夠看到噪點此刻繪製出來了,在爲其繪製幾條直線和曲線

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import random
import string

bg_color = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
width, height = 200, 80

im = Image.new("RGB", (width, height), bg_color)

draw = ImageDraw.Draw(im)

for _ in range(int(width * height * 0.1)):
    x_y_point = random.randint(0, width), random.randint(0, height)
    fill = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
    draw.point(x_y_point, fill)

for _ in range(5):
    """
    直線的長度要從畫板的左邊到,畫板的右邊
    所以左端點要在畫板左側上下變化
    所以右端點要在畫板右側上下變化
    """
    left_pos = 0, random.randint(0, height)
    right_pos = width, random.randint(0, height)
    fill = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
    draw.line([left_pos, right_pos], fill=fill)

# 再爲其繪製幾條曲線
for _ in range(5):
    """
    這裏咱們要超出畫板
    這樣最終在畫板上顯示的部分只是大圓的一條弧,看起來就像是一條曲線
    否則整個圓都顯示的話,就不是咱們想要的曲線了
    """
    left_pos = (-100, -100)
    right_pos = (width * 5, random.randint(0, height))
    fill = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
    draw.arc([left_pos, right_pos], 0, 360, fill=fill)

# 來看看長什麼樣
im.show()

能夠看到,背景的噪點和線段已經繪製完成,下面開始繪製文字

from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw
import random
import string

bg_color = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
width, height = 200, 80

im = Image.new("RGB", (width, height), bg_color)

draw = ImageDraw.Draw(im)

for _ in range(int(width * height * 0.1)):
    x_y_point = random.randint(0, width), random.randint(0, height)
    fill = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
    draw.point(x_y_point, fill)

for _ in range(5):
    left_pos = 0, random.randint(0, height)
    right_pos = width, random.randint(0, height)
    fill = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
    draw.line([left_pos, right_pos], fill=fill)

for _ in range(5):
    left_pos = (-100, -100)
    right_pos = (width * 5, random.randint(0, height))
    fill = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
    draw.arc([left_pos, right_pos], 0, 360, fill=fill)

# 驗證碼是由文字和數字組成,先來獲取全部的數字和字母
alpha_digit = string.ascii_letters + string.digits
# 驗證碼通常是四個字符,從裏面隨機選取4個
verify_code = random.sample(alpha_digit, 4)
# 生成字體對象
font = ImageFont.truetype(r"C:\Windows\Fonts\simkai.ttf", 40)
# 爲四個字符建立四種顏色
color = [(random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)) for _ in range(4)]

# 繪製文字
# 注意:座標加上字體的寬度不要超出畫板,不然顯示不全
draw.text([10, 10], verify_code[0], font=font, fill=color[0])
draw.text([60, 25], verify_code[1], font=font, fill=color[1])
draw.text([110, 15], verify_code[2], font=font, fill=color[2])
draw.text([150, 25], verify_code[3], font=font, fill=color[3])

# 釋放畫筆
del draw

# 再來查看一下
im.show()

驗證碼便被成功的繪製出來了


保存圖片

咱們以前的全部案例,都是調用show方法,自動將圖片打開。若是我想將圖片保存起來呢?要怎麼作呢?

from PIL import Image
import random

bg_color = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
width, height = 200, 80

im = Image.new("RGB", (width, height), bg_color)

# 若是我想將im保存起來的話,可使用save方法
# 指定文件名和格式
im.save("本地路徑.jpg", format="png")

這是一種方法,可是咱們生成驗證碼是爲了放在網站使用的,不可能先生成到本地,而後再讀取。所以咱們能夠把字節流放到緩存裏。

from PIL import Image
import random
from io import BytesIO

bg_color = random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
width, height = 200, 80

im = Image.new("RGB", (width, height), bg_color)

buf = BytesIO()
# save方法除了傳遞本地路徑,也能夠傳遞一個緩存,這樣字節流就都被放到了緩存裏
im.save(buf, "png")

# 有了緩存,那麼咱們就能夠直接在網站上渲染出驗證碼圖片。好比Django
# 咱們就可使用return HttpResponse(buf.getvalue(), "image/png"),直接渲染到頁面上

# 這裏咱們就用文件演示吧
with open("1.png", "wb") as f:
    f.write(buf.getvalue())



圖片轉成字符畫

from PIL import Image
def get_char(r, g, b, alpha=256):
    # 這些字符串是用來和圖片的像素進行匹配的
    ascii_char = '''$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:,\"^`'. '''
    if alpha == 0:
        return " "
    # 別問我爲何要這樣進行映射,我也不知道
    length = len(ascii_char)
    gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
    unit = (256.0+1)/length
    return ascii_char[int(gray/unit)]
 
def get_img(img: str, n: int):
    im = Image.open(img)
    # 有的時候,圖片太大了,生成的txt文件沒辦法所有顯示,須要拖動滾動條
    # 顯然這樣不爽,所以咱們能夠適當的縮小
    # 具體縮小多少倍,看圖片的狀況
    height = int(im.size[1]/n)
    width = int(im.size[0]/n)
  
    im = im.resize((width, height), Image.NEAREST)
    txt = ""
    for h in range(height):
        for w in range(width):
            # 獲取每個像素的三原色,匹配相應的字符
            txt += get_char(*im.getpixel((w, h)))
        # 注意換行,否則每一行的像素都合在一行了
        txt += "\n"
    return txt
 
# 調用main函數,只需傳入圖片,和生成的txt文件名以及縮小的倍數便可
def main(image_name: str, art_name: str, n: int=1):
    txt = get_img(image_name, n)
    with open(art_name, "w", encoding="utf-8") as f:
        f.write(txt)
if __name__ == '__main__':
    main(r"C:\Users\Administrator\Desktop\kanade.jpg", r"C:\Users\Administrator\Desktop\kanade.txt")



補充:圖像的一些格式

在PIL中,彩色圖片,打開以後返回的對象模式爲RGB或者RGBA,灰度圖像,返回對象的模式爲L。
通常狀況咱們可使用Image.open打開任意格式的圖片,而後保存的時候保存爲想要的格式。
可是Imgae對象能夠直接轉換格式,在PIL中共有1,L,P,RGB,RGBA,CMYK,YCbCr,I,F九種格式
from PIL import Image


im = Image.open("蕾姆.png")
im.show()

from PIL import Image


im = Image.open("蕾姆.png")
im1 = im.convert("1")
print(im1.mode)  # 1
im1.show()

from PIL import Image


im = Image.open("蕾姆.png")
im1 = im.convert("L")
"""
L = r * 299 / 1000 + g * 587 / 1000 + b * 114 / 1000
"""
print(im1.mode)  # L
im1.show()

from PIL import Image


im = Image.open("蕾姆.png")
im1 = im.convert("P")
print(im1.mode)  # P
im1.show()

from PIL import Image


im = Image.open("蕾姆.png")
im1 = im.convert("RGBA")
"""
模式rgba爲32位彩色圖像,它的每一個像素用32個bit表示,
其中24bit表示紅色、綠色、藍色三個通道,另外8位表示alpha通道,即透明通道
"""
print(im1.mode)  # RGBA
im1.show()

from PIL import Image


im = Image.open("蕾姆.png")
im1 = im.convert("CMYK")
"""
模式cmyk爲32位彩色圖像,它的每一個像素用32位表示
模式cmyk就是印刷四分色模式,它是彩色印刷是所採用的一種套色模式
利用色料的三原色混色原理,加上黑色油墨,共計四種顏色混合疊加,造成所謂的'全綵印刷'
C = 255 - R
M = 255 - G
Y = 255 - B
K = 0
"""
print(im1.mode)  # CMYK
im1.show()

from PIL import Image


im = Image.open("蕾姆.png")
im1 = im.convert("YCbCr")
"""
模式YCbCr爲24位彩色圖像,它的每一個像素用24位表示
YCbCr其中Y是指亮度份量,Cb是指藍色色度份量,而Cr是指紅色色度份量
人的肉眼對Y份量更加敏感,所以在經過對色度份量進行子採樣來減小色度份量後,肉眼將察覺不到圖像的質量變化
Y = 0.257 * R + 0.504 * G + 0.098 * B + 16
Cb = -0.148 * R - 0.291 * G + 0.439 * B + 128
Cr = 0.439 * R - 0.368 * G - 0.071 * B + 128
"""
print(im1.mode)  # YCbCr
im1.show()

from PIL import Image


im = Image.open("蕾姆.png")
im1 = im.convert("I")
"""
模式I爲32位整型灰色圖像,它的每一個像素用32位表示
0表示灰,255表示白,(0, 255)之間的數字表示不一樣的灰度
I = R * 299 / 1000 + G * 587 / 1000 + B * 114 / 1000 
"""
print(im1.mode)  # I
im1.show()

from PIL import Image


im = Image.open("蕾姆.png")
im1 = im.convert("F")
"""
模式I爲32位浮點灰色圖像,它的每一個像素用32位表示
0表示灰,255表示白,(0, 255)之間的數字表示不一樣的灰度
F = R * 299 / 1000 + G * 587 / 1000 + B * 114 / 1000

模式F和模式L的轉換公式是同樣的,都是RGB轉成灰色值的公式
但模式F會保留小數的部分 
"""
print(im1.mode)  # F
im1.show()

PIL還有一些其餘的模塊,這裏就不介紹了,由於不經常使用(實際上是你懶),目前的這些對於基本的圖像處理應該足夠了,固然若是後續想到了,會繼續添加

相關文章
相關標籤/搜索