Last Updated on 2021-05-17 by Clay
最近在開發自己感興趣的專案時,有了『點選圖片取得像素值』這樣的需求。這樣的需求我本來以為很常見,但查詢網路上後意外發現居然找不到什麼 Sample Code。(題外話,我剛打完這段字,突然有了興趣,再次丟 StackOverFlow,這次真的找到答案了,不過跟我想要的解答不太一樣)
為了讓以後有同樣需求的人或許能夠參考一下,我整理了下我嘗試出的辦法,讓各位見笑了。
如果對於 PyQt5 有興趣,可以參閱官方的指南: https://www.riverbankcomputing.com/static/Docs/PyQt5/index.html?highlight=qicon
或者是我之前寫過的 PyQt5 系列 的筆記。
解決辦法
我想的方法非常地簡單粗暴,但是我覺得還頗有效的。
- 重寫 QLabel 的 mousePressEvent(),讓我們知道點擊的座標
- 將 QLabel 的圖片轉成 PIL 的 Image,得到每個座標的像素值
- 將『滑鼠點擊的座標』跟『PIL Image 該座標』對應起來
經過上方簡單的三個步驟,我們就可以得到點擊座標的像素值了,其實意外簡單。
唯一需要小心的是,PIL Image 的座標跟滑鼠點擊的座標必須 Match 在一起才行。
假設我們有個 400 x 300 的圖片:
滑鼠點擊的座標 x 是 [0-399]、座標 y 則是 [0-299];PIL Image 的像素 Index 則是 [0-119999] ,故兩者之間的轉換公式應如下:
index = (y*400)+x
以下是我的 sample Code,也許可以參考一下:
# -*- coding: utf-8 -*- import sys from PyQt5.QtWidgets import * from PyQt5.QtGui import * from PIL import ImageQt class getColorLabel(QLabel): def __init__(self, widget): super(getColorLabel, self).__init__(widget) self.main = widget def mousePressEvent(self, event): self.main.get(event.pos()) class MainWindow(QWidget): def __init__(self): super(MainWindow, self).__init__() self.resize(800, 600) self.setWindowTitle('Drop Event Test') # Get Position self.label = getColorLabel(self) self.label.setGeometry(200, 250, 400, 300) self.label.setPixmap(QPixmap('test.png')) self.label.setScaledContents(True) # Display self.displayLabel = QLabel(self) self.displayLabel.setGeometry(300, 0, 200, 200) self.displayLabel.setStyleSheet('background-color: rgb(255, 255, 255);') def get(self, pos): index = pos.y()*self.label.size().width()+pos.x() image = ImageQt.fromqpixmap(self.label.pixmap()) image = image.resize((self.label.size().width(), self.label.size().height())) image_data = image.getdata() r, g, b = image_data[index] self.displayLabel.setStyleSheet('background-color: rgb({},{},{});'.format(r, g, b)) if __name__ == '__main__': app = QApplication([]) window = MainWindow() window.show() sys.exit(app.exec_())
Output:
我使用有了隨手畫的一張圖來作範例,可以將點選位置的顏色放到上面的 Label。
以上就是我嘗試點選位置得到像素值的心得筆記。