Эта тема вызвала довольно много проблем из-за различий в языках, но в итоге все довольно просто.
Основные проблемы:
1 - создание массива cvMat из имеющегося тьюпла
2 - чтение данных из массива
3 - сама технология создания нового массива
Итак, посмотрим, что у меня получилось:
Программа №1 - создание матрицы, работа с ее элементами
Программа №2 - ROI несколько способов задания области интересов
()() "=" в питоне: Присваивание в Python происходит следующим образом: если присваеваемый объект является экземпляром таких типов как числа или строки, то действует семантика копирования, если же в правой части стоит экземпляр класса, список, словарь или тьюпл, то действует семантика указателей. ()()
Т.е. в функции subimage() я имею не несколько отдельных картинок, у каждой из которых есть своя область в памяти, на самом деле в моем распоряжении имена, ссылающиеся на область памяти, занятую данными загруженной картинкой (вот почему при сдвиге пикселей определенного канала меняется и главное изображение - данные то одни).
Ну и третья функция показывает, зачем же все-таки оставили хедеры - как результат мы получаем не новое имя, ссылающееся на часть данных картинки, а полностью самостоятельное изображение, имеющее свою область памяти.
Программа №3 - альфа-слияние
Процедура знакомая многим по работе в Photoshop
Так же отсутствие функций Release*Header и т.д. натолкнули на мысль, что при работе с языком питон нет смысла в этих функциях, т.к. не работая напрямую с памятью мы там и не сорим, и все уберут за нас, поэтому и функции DestroyWindow или ReleaseCapture смысла тоже не имеют, и их оставили, наверное, только для сохранения общей структуры приложения на OpenCV, поэтому в этих приложениях я не использовал эти функции, так же как и создание именованного окна, оно создается автоматически при попытке отобразить изображение.
Основные проблемы:
1 - создание массива cvMat из имеющегося тьюпла
2 - чтение данных из массива
3 - сама технология создания нового массива
Итак, посмотрим, что у меня получилось:
Программа №1 - создание матрицы, работа с ее элементами
import cv,numpy def main(): mat=cv.CreateMat(2,2,cv.CV_32FC1) mat[1,1]=2.0 print mat[1,1] print cv.Get2D(mat,1,1) return '****' def sub(): vals=((1.0,2.0),(3.0,4.0)) a=numpy.array(vals) b=cv.fromarray(a) mat=cv.CreateMatHeader(2,2,cv.CV_32FC1) cv.SetData(mat,b.tostring()) print mat[1,1] print cv.Get2D(mat,1,1) return '****' if __name__ == '__main__': print main() print sub()Коментарии - т.к. в питоне, как я уже говорил, нельзя работать с указателями и памятью, то все структуры были сильно упрощены, итого мы имеем: данные в cvMat хранятся в виде строки, доступ можно осуществлять, как к обычному массиву (mat[1,1]) ну и самое трудное - засунуть имеющийся тьюпл в cvMat, для этого я использовал библиотеку numpy(которая широко применяется параллельно с OpenCV для решения задач), а схема проста, мы имеем тьюпл, с помощью array() создаем для него интерфейс массива, затем с помощью formarray делаем массив типа cvMat ну и наконец присваиваем ему его новый заголовок (имя) (конечно можно остановиться после formarray, но хотелось попробовать использовать SetData). Так же, как мы видим cv.Get*D возвращает значение типа cvScalar, а не float, которое мы записывали.
Программа №2 - ROI несколько способов задания области интересов
import cv
def roi():
cv.SetImageROI(src,rctBlue)
cv.AddS(src,offsetBlue,src)
cv.ResetImageROI(src)
cv.SetImageROI(src,rctGreen)
cv.AddS(src,offsetGreen,src)
cv.ResetImageROI(src)
cv.SetImageROI(src,rctRed)
cv.AddS(src,offsetRed,src)
cv.ResetImageROI(src)
cv.ShowImage("Main",src)
return 0
def subimage():
subimg=cv.GetSubRect(src2, rctBlue)
subimg2=cv.GetSubRect(src2, rctGreen)
subimg3=cv.GetSubRect(src2, rctRed)
cv.AddS(subimg,offsetBlue,subimg)
cv.AddS(subimg2,offsetGreen,subimg2)
cv.AddS(subimg3,offsetRed,subimg3)
cv.ShowImage('Sub',src2)
return 0
def subimage_ext():
subimg=cv.CreateImageHeader((rctBlue[0],rctBlue[-1]),
src3.depth,src3.nChannels)
cv.SetData(subimg,cv.GetSubRect(src3,rctBlue).tostring())
cv.AddS(subimg,offsetBlue,subimg)
cv.ShowImage('Subsub-main',src3)
cv.ShowImage('Subsub-sub',subimg)
return 0
if __name__ == '__main__':
offsetBlue=cv.Scalar(150)
offsetGreen=cv.Scalar(0,150)
offsetRed=cv.Scalar(0,0,150)
rctBlue=(100,100,100,100)
rctGreen=(200,100,100,100)
rctRed=(150,200,100,100)
src=cv.LoadImage('1.jpg')
src2=cv.LoadImage('1.jpg')
src3=cv.LoadImage('1.jpg')
print roi()
print subimage()
print subimage_ext()
cv.WaitKey(0)
Коментарии - Здесь я долго ковырялся, пытаясь сообразить как переделать Cкод на питон, т.к. все функции типа Create*Header и т.д. не имеют смысла в питоне, где мы не можем работать с указателями и т.д. + я обнаружил интересную систему работы присваивания, которая оказалась весьма удобной (изначально я думал придется пользоваться самым неудобным способом - SetImageROI (функция roi()))()() "=" в питоне: Присваивание в Python происходит следующим образом: если присваеваемый объект является экземпляром таких типов как числа или строки, то действует семантика копирования, если же в правой части стоит экземпляр класса, список, словарь или тьюпл, то действует семантика указателей. ()()
Т.е. в функции subimage() я имею не несколько отдельных картинок, у каждой из которых есть своя область в памяти, на самом деле в моем распоряжении имена, ссылающиеся на область памяти, занятую данными загруженной картинкой (вот почему при сдвиге пикселей определенного канала меняется и главное изображение - данные то одни).
Ну и третья функция показывает, зачем же все-таки оставили хедеры - как результат мы получаем не новое имя, ссылающееся на часть данных картинки, а полностью самостоятельное изображение, имеющее свою область памяти.
Программа №3 - альфа-слияние
Процедура знакомая многим по работе в Photoshop
import cv
def main():
cv.SetImageROI(src1,rectAlpha1)
cv.SetImageROI(src2,rectBeta)
cv.AddWeighted(src1,alpha,src2,beta,gamma,src1)
cv.ResetImageROI(src1)
cv.SetImageROI(src1,rectAlpha2)
cv.AddWeighted(src1,alpha1,src2,beta1,gamma,src1)
cv.ResetImageROI(src1)
cv.SetImageROI(src1,rectAlpha3)
cv.AddWeighted(src1,alpha,src2,beta,gamma1,src1)
cv.ResetImageROI(src1)
cv.ShowImage('Main2',src1)
return 0
if __name__ == '__main__':
src1=cv.LoadImage('1.jpg')
src2=cv.LoadImage('2.bmp')
rectBeta=(120,150,80,100)
rectAlpha1=(0,0,80,100)
rectAlpha2=(0,100,80,100)
rectAlpha3=(0,200,80,100)
gamma1=0.7
alpha1=0.2
beta1=0.8
gamma=0.0
alpha=0.5
beta=0.5
print main()
cv.WaitKey(0)
Так же отсутствие функций Release*Header и т.д. натолкнули на мысль, что при работе с языком питон нет смысла в этих функциях, т.к. не работая напрямую с памятью мы там и не сорим, и все уберут за нас, поэтому и функции DestroyWindow или ReleaseCapture смысла тоже не имеют, и их оставили, наверное, только для сохранения общей структуры приложения на OpenCV, поэтому в этих приложениях я не использовал эти функции, так же как и создание именованного окна, оно создается автоматически при попытке отобразить изображение.
Комментариев нет:
Отправить комментарий