提取图像的最大像素值的位置

时间:2019-07-31 08:42:10

标签: python image-processing

我是这里的新手。我正在尝试获得2D火焰边缘的单线,然后可以计算实际面积-3D火焰面积。首先是要获得优势。 2D火焰是从侧面看的凹面火焰,因此火焰底部(平坦部分)比凹面段更亮。我使用下面的代码查找边缘,我的方法是沿着y轴查找最大像素值。结果似乎没有达到我的目的,请您帮我弄清楚吗?首先十分感谢。 Original image在代码中,我旋转图像

from PIL import Image
import numpy as np
import cv2

def initialization_rotate(path):
    global h,w,img
    img4 = np.array(Image.open(path).convert('L'))
    img3 = img4.transpose(1,0)
    img2 = img3[::-1,::1]
    img = img2[400:1000,1:248]
    h, w = img.shape

path = 'D:\\20190520\\14\\14\\1767.jpg'

#Noise cancellation
def opening(binary):
    opened = np.zeros_like(binary)              
    for j in range(1,w-1):
        for i in range(1,h-1):
            if binary[i][j]> 100:
                n1 = binary[i-1][j-1]
                n2 = binary[i-1][j]
                n3 = binary[i-1][j+1]
                n4 = binary[i][j-1]
                n5 = binary[i][j+1]
                n6 = binary[i+1][j-1]
                n7 = binary[i+1][j]
                n8 = binary[i+1][j+1]
                sum8 = int(n1) + int(n2) + int(n3) + int(n4) + int(n5) + int(n6) + int(n7) + int(n8)
                if sum8 < 1000:
                    opened[i][j] = 0
                else:
                    opened[i][j] = 255
            else:
                pass
    return opened    


edge = np.zeros_like(img)


# Find the max pixel value and extract the postion
for j in range(w-1):
    ys = [0]
    ymax = []
    for i in range(h-1):
         if img[i][j] > 100:
            ys.append(i)
        else:
            pass
    ymax = np.amax(ys)
    edge[ymax][j] = 255


cv2.namedWindow('edge')

while(True):
    cv2.imshow('edge',edge)
    k = cv2.waitKey(1) & 0xFF
    if k == 27:
        break


cv2.destroyAllWindows()

2 个答案:

答案 0 :(得分:0)

我从头开始进行了非常快速的编码(没有研究边缘检测方面已建立的或最新的算法)。不是很令人惊讶,结果非常差。我下面粘贴的代码仅适用于RGB(即仅适用于三个通道,不适用于CMYK,灰度或RGBA或其他任何图像)。我也对单个非常简单的图像进行了测试。在现实生活中,图像非常复杂。我认为那还不很理想。它需要很多工作。但是,我很犹豫地分享它,因为@Gia Tri要求这样做。

这就是我所做的。对于每一列,我计算了平均强度和stddev强度。我希望边缘处的强度会与平均+ -stdev(乘以一个因子)相比发生变化。如果我在该列中标记了第一列和最后一个列,则每列都将具有边缘,并且希望在缝合后将形成边缘。代码和所附的图像供您查看,我的情况如何。

from scipy import ndimage
import numpy as np
import matplotlib.pyplot as plt

UppperStdBoundaryMultiplier = 1.0
LowerStdBoundaryMultiplier = 1.0
NegativeSelection = False

def SumSquareRGBintensityOfPixel(Pixel):
    return np.sum(np.power(Pixel,2),axis=0)

def GetTheContinousStretchForAcolumn(Column):
    global UppperStdBoundaryMultiplier
    global LowerStdBoundaryMultiplier
    global NegativeSelection
    SumSquaresIntensityOfColumn = np.apply_along_axis(SumSquareRGBintensityOfPixel,1,Column)
    Mean = np.mean(SumSquaresIntensityOfColumn)
    StdDev = np.std(SumSquaresIntensityOfColumn)
    LowerThreshold = Mean - LowerStdBoundaryMultiplier*StdDev
    UpperThreshold = Mean + UppperStdBoundaryMultiplier*StdDev
    if NegativeSelection:
        Index = np.where(SumSquaresIntensityOfColumn < LowerThreshold)
        Column[Index,:] = np.array([255,255,255])
    else:
        Index = np.where(SumSquaresIntensityOfColumn >= LowerThreshold)
        LeastIndex = Index[Index==True][0]
        LastIndex = Index[Index==True][-1]
        Column[[LeastIndex,LastIndex],:] =  np.array([255,0,0])
    return Column

def DoEdgeDetection(ImageFilePath):
    FileHandle = ndimage.imread(ImageFilePath)
    for Column in range(FileHandle.shape[1]):
        FileHandle[:,Column,:] = GetTheContinousStretchForAcolumn(FileHandle[:,Column,:])
    plt.imshow(FileHandle)
    plt.show()

DoEdgeDetection("/PathToImage/Image_1.jpg")

结果如下。左边是必须检测边缘的查询图像,右边是边缘检测图像。边缘点用红点标记。如您所见,它的表现很差,但是花费了一些时间和精力,它可能会做得更好……也许不是。也许这是一个不错的开始,但还远未完成。.,请成为裁判!

May be a good start but far from finish

*****明确了GiaTri的要求后进行编辑***************

所以我确实设法更改了程序,但想法还是一样。但是,这次将问题过度简化为仅检测蓝色火焰的情况。实际上,我继续进行操作,并使它可用于所有三个颜色通道。但是,我怀疑,这对您来说对蓝色通道以外的地区是否有用。

**如何使用下面的程序**

如果您的火焰是垂直的,则在课堂作业中选择edge =“ horizo​​ntal”。如果您的边缘是水平的,则选择edges =“ vertical”。这可能有点令人困惑,但暂时请使用它。以后您可以更改它,也可以更改它。

因此,首先让我说服您,边缘检测的性能要比昨天好得多。请参阅下面的两个图像。我已经从互联网上拍摄了这两个火焰图像。与之前一样,必须检测边缘的图像在左侧和右侧是边缘检测的图像。边缘为红点。

第一个horizontal flame

Horizontal flame detected

然后是a vertical flame

Vertical flame detected

这方面还有很多工作要做。但是,如果您比昨天更确信,那么下面是代码。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.image import imread

class DetectEdges():

    def __init__(self, ImagePath, Channel = ["blue"], edges="vertical"):
        self.Channel = Channel
        self.edges = edges
        self.Image_ = imread(ImagePath)
        self.Image = np.copy(self.Image_)
        self.Dimensions_X, self.Dimensions_Y, self.Channels = self.Image.shape
        self.BackGroundSamplingPercentage = 0.5

    def ShowTheImage(self):
        plt.imshow(self.Image)
        plt.show()

    def GetTheBackGroundPixels(self):
        NumberOfPoints = int(self.BackGroundSamplingPercentage*min(self.Dimensions_X, self.Dimensions_Y))
        Random_X = np.random.choice(self.Dimensions_X, size=NumberOfPoints, replace=False)
        Random_Y = np.random.choice(self.Dimensions_Y, size=NumberOfPoints, replace=False)
        Random_Pixels = np.array(list(zip(Random_X,Random_Y)))
        return Random_Pixels

    def GetTheChannelEdge(self):
        BackGroundPixels = self.GetTheBackGroundPixels()
        if self.edges == "vertical":
            if self.Channel == ["blue"]:
                MeanBackGroundInensity = np.mean(self.Image[BackGroundPixels[:,0],BackGroundPixels[:,1],2])
                for column in range(self.Dimensions_Y):
                    PixelsAboveBackGround = np.where(self.Image[:,column,2]>MeanBackGroundInensity)
                    if PixelsAboveBackGround[PixelsAboveBackGround==True].shape[0] > 0:
                        TopPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][0]
                        BottomPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][-1]
                        self.Image[[TopPixel,BottomPixel],column,:] = [255,0,0]
            if self.Channel == ["red"]:
                MeanBackGroundInensity = np.mean(self.Image[BackGroundPixels[:,0],BackGroundPixels[:,1],0])
                for column in range(self.Dimensions_Y):
                    PixelsAboveBackGround = np.where(self.Image[:,column,0]>MeanBackGroundInensity)
                    if PixelsAboveBackGround[PixelsAboveBackGround==True].shape[0] > 0:
                        TopPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][0]
                        BottomPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][-1]
                        self.Image[[TopPixel,BottomPixel],column,:] = [0,255,0]
            if self.Channel == ["green"]:
                MeanBackGroundInensity = np.mean(self.Image[BackGroundPixels[:,0],BackGroundPixels[:,1],1])
                for column in range(self.Dimensions_Y):
                    PixelsAboveBackGround = np.where(self.Image[:,column,1]>MeanBackGroundInensity)
                    if PixelsAboveBackGround[PixelsAboveBackGround==True].shape[0] > 0:
                        TopPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][0]
                        BottomPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][-1]
                        self.Image[[TopPixel,BottomPixel],column,:] = [255,0,0]
        elif self.edges=="horizontal":
            if self.Channel == ["blue"]:
                MeanBackGroundInensity = np.mean(self.Image[BackGroundPixels[:,0],BackGroundPixels[:,1],2])
                for row in range(self.Dimensions_X):
                    PixelsAboveBackGround = np.where(self.Image[row,:,2]>MeanBackGroundInensity)
                    if PixelsAboveBackGround[PixelsAboveBackGround==True].shape[0] > 0:
                        LeftPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][0]
                        RightPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][-1]
                        self.Image[row,[LeftPixel,RightPixel],:] = [255,0,0]
            if self.Channel == ["red"]:
                MeanBackGroundInensity = np.mean(self.Image[BackGroundPixels[:,0],BackGroundPixels[:,1],0])
                for row in range(self.Dimensions_X):
                    PixelsAboveBackGround = np.where(self.Image[row,:,0]>MeanBackGroundInensity)
                    if PixelsAboveBackGround[PixelsAboveBackGround==True].shape[0] > 0:
                        LeftPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][0]
                        RightPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][-1]
                        self.Image[row,[LeftPixel,RightPixel],:] = [0,255,0]
            if self.Channel == ["green"]:
                MeanBackGroundInensity = np.mean(self.Image[BackGroundPixels[:,0],BackGroundPixels[:,1],1])
                for row in range(self.Dimensions_X):
                    PixelsAboveBackGround = np.where(self.Image[row,:,1]>MeanBackGroundInensity)
                    if PixelsAboveBackGround[PixelsAboveBackGround==True].shape[0] > 0:
                        LeftPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][0]
                        RightPixel = PixelsAboveBackGround[PixelsAboveBackGround==True][-1]
                        self.Image[row,[LeftPixel,RightPixel],:] = [255,0,0]



Test = DetectEdges("FlameImagePath",Channel = ["blue"],edges="vertical")
Test.GetTheChannelEdge()
Test.ShowTheImage()

请告诉我这是否有“更多”帮助,或者我错过了一些重要要求。

最良好的祝愿

答案 1 :(得分:0)

顺便说一句,阿米特(Amit),我想使用阈值像素值的思想来展示我的代码。我很想与您讨论。

if __name__ == '__main__':
    path = 'D:\\20181229__\\7\\Area 7\\1767.jpg'
    img1 = cv2.imread(path)
    b,g,r = cv2.split(img1)
    img3 = b[94:223, 600:700]
    img4 = cv2.flip(img3, 1)
    h,w = img3.shape
    data = []
    th_val = 20
    for i in range(h):
        for j in range(w):
            val = img3[i, -j]
            if (val >= th_val):
                data.append(j)
                break

    x = range(len(data))
    plt.figure(figsize = (10, 7))
    plt.subplot(121)
    plt.imshow(img4)
    plt.plot(data, x)
    plt.subplot(121)
    plt.plot(data, x)

请查看结果链接。问题是该方法仍然不能完全满足我的需求。希望与您讨论。 链接:https://imgur.com/QtNk7c7