Beispiel #1
0
def mainTurnHR():
    '''1. read img LR and HR'''
    imgLRPath = '../../github/vrn-07231340/examples/scaled/trump_12.jpg'
    imgLR = cv2.imread(imgLRPath)
    imgHRPath = '../../github/vrn-07231340/examples/trump_12.png'
    imgHR = cv2.imread(imgHRPath)
    objPath = '../../github/vrn-07231340/obj/trump_12.obj'

    '''2. img LR --> HR'''
    zRatio = 3
    objLinesHR, vLinesHR, landmarkLR, landmarkHR = lr2hr3DModel(
        imgLR, imgHR, zRatio, objPath)

    '''3. HR: origin 2D landmark --> origin 3D landmark'''
    originLandmark3DList = getLandmark3DHR(landmarkHR, vLinesHR)
    originLandmark3DList = optionChooseZMax(originLandmark3DList)
    faceLandmarkVlines = []
    for (_, _, (_, vLine)) in originLandmark3DList:
        faceLandmarkVlines.append(vLine)

    '''4. HR: collar detection'''
    _, collarPoint = collarDetection(imgHR, minSize=1200, offset=15)

    '''5. HR: hair detection'''
    originHairPoints = hairDetection(imgHR, minSize=20000)

    '''5.1 hair points 不应该全部都在一个平面上(minZ=200),他们应该在一个曲面上'''
    '''    取XZ平面上face landmark的三个极点,画一个圆'''
    '''    除了face landmark以外的所有点 的 z,都落到圆上'''
    '''5.1.1 face landmark上XZ平面的三个极点'''
    faceLandmarkOnXZ = []
    for faceLandmarkVline in faceLandmarkVlines:
        v, x, y, z, r, g, b = faceLandmarkVline.split()
        faceLandmarkOnXZ.append((float(x), float(z)))
    faceLandmarkOnXZMinX = min(faceLandmarkOnXZ, key=lambda x: x[0])
    faceLandmarkOnXZMaxX = max(faceLandmarkOnXZ, key=lambda x: x[0])
    faceLandmarkOnXZMaxZ = max(faceLandmarkOnXZ, key=lambda x: x[1])

    '''5.1.2 三点构成一个圆'''
    circleCenterXOnXZ, circleCenterZOnXZ, radiusOnXZ = threePoints2Circle(
        faceLandmarkOnXZMinX, faceLandmarkOnXZMaxX, faceLandmarkOnXZMaxZ)
    circleCenterZOnXZ = circleCenterZOnXZ-70
    '''5.1.3 把这个圆扩大,圆心不动,半径扩大至hair points的极点'''
    k1 = abs(circleCenterXOnXZ-max(originHairPoints, key=lambda x: x[0])[0])
    k2 = abs(circleCenterXOnXZ-min(originHairPoints, key=lambda x: x[0])[0])
    radiusOnXZ = max([k1, k2])+5
    rr, cc = circle_perimeter(int(circleCenterXOnXZ), int(
        circleCenterZOnXZ), int(radiusOnXZ))
    circleOnXZ = np.dstack([rr, cc])[0]
    '''5.1.4 hair points 的 z 落在圆上'''
    hairPointsVlines = []
    for (x, y) in originHairPoints:
        maxZ = 0
        for (x0, z0) in circleOnXZ:
            if int(x) == int(x0):
                if z0 > maxZ:
                    maxZ = z0
        hairVline = '{} {} {} {} {} {} {}'.format('v', x, y, maxZ, 0, 0, 0)
        hairPointsVlines.append(hairVline)
        maxZ = 0

    assert len(hairPointsVlines) == len(originHairPoints)

    '''6. HR: face landmarks + hair points'''
    originVlines = faceLandmarkVlines+hairPointsVlines

    '''7. HR: turn face and hair'''
    turnAngle = 10
    turnDirection = ['left', 'right']
    turnCenterMode = 'maxY'
    leftTurnVLines = turnHR(originVlines, turnAngle,
                            turnDirection[0], turnCenterMode)
    rightTurnVLines = turnHR(originVlines, turnAngle,
                             turnDirection[1], turnCenterMode)

    assert len(originVlines) == len(leftTurnVLines) == len(rightTurnVLines)

    '''8. HR: turn 3D --> 2D'''
    originPointsHR = []
    leftTurnPointsHR = []
    rightTurnPointsHR = []
    for originVline, leftTurnVLine, rightTurnVLine in zip(originVlines, leftTurnVLines, rightTurnVLines):
        _, x, y, _, _, _, _ = originVline.split()
        originPointsHR.append((float(x), float(y)))
        _, x, y, _, _, _, _ = leftTurnVLine.split()
        leftTurnPointsHR.append((float(x), float(y)))
        _, x, y, _, _, _, _ = rightTurnVLine.split()
        rightTurnPointsHR.append((float(x), float(y)))

    assert len(originPointsHR) == len(
        leftTurnPointsHR) == len(rightTurnPointsHR)

    # drawPointsOnImg(originPointsHR, imgHR, 'g')
    # drawPointsOnImg(turnPointsHR, imgHR, 'r')

    ''''9. inner ellipse'''
    left = min(originPointsHR, key=lambda x: x[0])[0]
    right = max(originPointsHR, key=lambda x: x[0])[0]
    up = min(originPointsHR, key=lambda x: x[1])[1]
    bottom = max(originPointsHR, key=lambda x: x[1])[1]
    innerEllipseCenterX = int((left+right)/2.0)
    innerEllipseCenterY = int((up+bottom)/2.0)
    innerEllipseSemiX = int((right-left)/2.0)
    innerEllipseSemiY = int((bottom-up)/2.0)
    rr, cc = ellipse_perimeter(innerEllipseCenterX, innerEllipseCenterY,
                               innerEllipseSemiY, innerEllipseSemiX, orientation=np.pi*1.5)
    innerEllipseVerts = np.dstack([rr, cc])[0]

    '''10. outer ellipse'''
    '''10.1 ratio = outer ellipse / inner ellipse'''
    '''     椭圆心和衣领的线段  和  椭圆的交点'''
    minDistance = np.inf
    for pt in innerEllipseVerts:
        distance = twoPointsDistance(pt, collarPoint)
        if distance < minDistance:
            minDistance = distance
            ratio = twoPointsDistance((innerEllipseCenterX, innerEllipseCenterY), collarPoint) / \
                twoPointsDistance(
                    (innerEllipseCenterX, innerEllipseCenterY), pt)
    '''10.2 outer ellipse'''
    outerEllipseSemiX = int(ratio*innerEllipseSemiX)
    outerEllipseSemiY = int(ratio*innerEllipseSemiY)
    rr, cc = ellipse_perimeter(innerEllipseCenterX, innerEllipseCenterY,
                               outerEllipseSemiY, outerEllipseSemiX, orientation=np.pi*1.5)
    outerEllipseVerts = np.dstack([rr, cc])[0]
    # drawPointsOnImg(outerEllipseVerts, imgHR, 'g')

    '''11. edge points on outer ellipse'''
    edgePoints = edgePointsOnOuterEllipse(outerEllipseVerts)

    '''12. final origin and turn points'''
    originPointsHRFinal = originPointsHR+edgePoints
    leftTurnPointsHRFinal = leftTurnPointsHR+edgePoints
    rightTurnPointsHRFinal = rightTurnPointsHR+edgePoints

    '''13. tri.txt'''
    triList = generateTriList(
        originPointsHRFinal, imgHR, triTxtPath='./turnTri.txt')

    '''14. warp'''
    # imgMorph = morph_modify_for_2D3D2D_low_resolution(
    #     originPointsHRFinal, turnPointsHRFinal, imgHR, triList)
    # imshow('imgMorph', imgMorph)
    # cv2.imwrite('./imgMorph.png', imgMorph)

    return originPointsHRFinal, leftTurnPointsHRFinal, rightTurnPointsHRFinal, triList
Beispiel #2
0
def mainNodHR():
    '''1. read img LR and HR'''
    imgLRPath = '../../github/vrn-07231340/examples/scaled/trump-12.jpg'
    imgLR = cv2.imread(imgLRPath)
    imgHRPath = '../../github/vrn-07231340/examples/trump-12.jpg'
    imgHR = cv2.imread(imgHRPath)
    objPath = '../../github/vrn-07231340/obj/trump-12.obj'
    '''2. img LR --> HR'''
    zRatio = 3
    objLinesHR, vLinesHR, landmarkLR, landmarkHR = lr2hr3DModel(
        imgLR, imgHR, zRatio, objPath)
    '''3. HR: origin 2D landmark --> origin 3D landmark'''
    originLandmark3DList = getLandmark3DHR(landmarkHR, vLinesHR)
    originLandmark3DList = optionChooseZMax(originLandmark3DList)
    faceLandmarkVlines = []
    for (_, _, (_, vLine)) in originLandmark3DList:
        faceLandmarkVlines.append(vLine)
    '''4. HR: collar detection'''
    _, collarPoint = collarDetection(imgHR, minSize=1200, offset=15)
    '''5. HR: hair detection'''
    originHairPoints = hairDetection(imgHR, minSize=20000)
    # minZ = maxminXYZ(objLinesHR)['minZCoord'][2]
    minZ = 180
    hairPointsVlines = []
    for (x, y) in originHairPoints:
        hairVline = '{} {} {} {} {} {} {}'.format('v', x, y, minZ, 0, 0, 0)
        hairPointsVlines.append(hairVline)
    '''6. HR: face landmarks + hair points'''
    originVlines = faceLandmarkVlines + hairPointsVlines
    '''7. HR: nod face and hair'''
    nodAngle = 15
    nodCenterMode = 'maxY'
    nodVlines = nodHR(originVlines, nodAngle, nodCenterMode)

    assert len(originVlines) == len(nodVlines)
    '''8. HR: nod 3D --> 2D'''
    originPointsHR = []
    nodPointsHR = []
    for originVline, nodVline in zip(originVlines, nodVlines):
        _, x, y, _, _, _, _ = originVline.split()
        originPointsHR.append((float(x), float(y)))
        _, x, y, _, _, _, _ = nodVline.split()
        nodPointsHR.append((float(x), float(y)))

    assert len(originPointsHR) == len(nodPointsHR)

    # drawPointsOnImg(originPointsHR, imgHR, 'g', radius=2)
    # drawPointsOnImg(nodPointsHR, imgHR, 'r', radius=2)
    ''''9. inner ellipse'''
    left = min(originPointsHR, key=lambda x: x[0])[0]
    right = max(originPointsHR, key=lambda x: x[0])[0]
    up = min(originPointsHR, key=lambda x: x[1])[1]
    bottom = max(originPointsHR, key=lambda x: x[1])[1]
    innerEllipseCenterX = int((left + right) / 2.0)
    innerEllipseCenterY = int((up + bottom) / 2.0)
    innerEllipseSemiX = int((right - left) / 2.0)
    innerEllipseSemiY = int((bottom - up) / 2.0)
    rr, cc = ellipse_perimeter(innerEllipseCenterX,
                               innerEllipseCenterY,
                               innerEllipseSemiY,
                               innerEllipseSemiX,
                               orientation=np.pi * 1.5)
    innerEllipseVerts = np.dstack([rr, cc])[0]
    '''10. outer ellipse'''
    '''10.1 ratio = outer ellipse / inner ellipse'''
    '''     椭圆心和衣领的线段  和  椭圆的交点'''
    minDistance = np.inf
    for pt in innerEllipseVerts:
        distance = twoPointsDistance(pt, collarPoint)
        if distance < minDistance:
            minDistance = distance
            ratio = twoPointsDistance((innerEllipseCenterX, innerEllipseCenterY), collarPoint) / \
                twoPointsDistance(
                    (innerEllipseCenterX, innerEllipseCenterY), pt)
    '''10.2 outer ellipse'''
    outerEllipseSemiX = int(ratio * innerEllipseSemiX)
    outerEllipseSemiY = int(ratio * innerEllipseSemiY)
    rr, cc = ellipse_perimeter(innerEllipseCenterX,
                               innerEllipseCenterY,
                               outerEllipseSemiY,
                               outerEllipseSemiX,
                               orientation=np.pi * 1.5)
    outerEllipseVerts = np.dstack([rr, cc])[0]
    '''11. edge points on outer ellipse'''
    edgePoints = edgePointsOnOuterEllipse(outerEllipseVerts)
    '''12. final origin and nod points'''
    originPointsHRFinal = originPointsHR + edgePoints
    nodPointsHRFinal = nodPointsHR + edgePoints
    assert len(originPointsHRFinal) == len(nodPointsHRFinal)
    '''13. tri.txt'''
    triList = generateTriList(originPointsHRFinal,
                              imgHR,
                              triTxtPath='./nodTri.txt')
    '''14. warp'''
    imgMorph = morph_modify_for_2D3D2D_low_resolution(originPointsHRFinal,
                                                      nodPointsHRFinal, imgHR,
                                                      triList)
    imshow('imgMorph', imgMorph)
    cv2.imwrite('./imgMorph.png', imgMorph)

    return originPointsHRFinal, nodPointsHRFinal, triList
Beispiel #3
0
def mainTurnHRHairOnEllipsoid():
    '''1. read img LR and HR'''
    imgLRPath = '../../github/vrn-07231340/examples/scaled/trump_12.jpg'
    imgLR = cv2.imread(imgLRPath)
    imgHRPath = '../../github/vrn-07231340/examples/trump_12.png'
    imgHR = cv2.imread(imgHRPath)
    objPath = '../../github/vrn-07231340/obj/trump_12.obj'

    '''2. img LR --> HR'''
    zRatio = 3
    objLinesHR, vLinesHR, landmarkLR, landmarkHR = lr2hr3DModel(
        imgLR, imgHR, zRatio, objPath)

    '''3. HR: origin 2D landmark --> origin 3D landmark'''
    originLandmark3DList = getLandmark3DHR(landmarkHR, vLinesHR)
    originLandmark3DList = optionChooseZMax(originLandmark3DList)
    faceLandmarkVlines = []
    for (_, _, (_, vLine)) in originLandmark3DList:
        faceLandmarkVlines.append(vLine)

    '''4. HR: collar detection'''
    _, collarPoint = collarDetection(imgHR, minSize=1200, offset=15)

    '''5. HR: hair detection'''
    originHairPoints = hairDetection(imgHR, minSize=20000)
    '''5.1 hair vLines z = -1'''
    hairPointsVlines = []
    for (x, y) in originHairPoints:
        hairVline = '{} {} {} {} {} {} {}'.format('v', x, y, -1, 0, 0, 0)
        hairPointsVlines.append(hairVline)

    '''6. HR: origin vLines = face landmark vLines + hair vLines'''
    originVlines = faceLandmarkVlines+hairPointsVlines

    '''7. HR: origin points'''
    originPointsHR = []
    for originVline in originVlines:
        _, x, y, _, _, _, _ = originVline.split()
        originPointsHR.append((float(x), float(y)))

    '''8. inner ellipse'''
    left = min(originPointsHR, key=lambda x: x[0])[0]
    right = max(originPointsHR, key=lambda x: x[0])[0]
    up = min(originPointsHR, key=lambda x: x[1])[1]
    bottom = max(originPointsHR, key=lambda x: x[1])[1]
    innerEllipseCenterX = int((left+right)/2.0)
    innerEllipseCenterY = int((up+bottom)/2.0)
    innerEllipseSemiX = int((right-left)/2.0)
    innerEllipseSemiY = int((bottom-up)/2.0)
    rr, cc = ellipse_perimeter(innerEllipseCenterX, innerEllipseCenterY,
                               innerEllipseSemiY, innerEllipseSemiX, orientation=np.pi*1.5)
    innerEllipseVerts = np.dstack([rr, cc])[0]
    # drawPointsOnImg(innerEllipseVerts, imgHR, 'g')

    '''9. outer ellipse'''
    '''9.1 ratio = outer ellipse / inner ellipse'''
    '''     椭圆心和衣领的线段  和  椭圆的交点'''
    minDistance = np.inf
    for pt in innerEllipseVerts:
        distance = twoPointsDistance(pt, collarPoint)
        if distance < minDistance:
            minDistance = distance
            ratio = twoPointsDistance((innerEllipseCenterX, innerEllipseCenterY), collarPoint) / \
                twoPointsDistance(
                    (innerEllipseCenterX, innerEllipseCenterY), pt)
    '''9.2 outer ellipse'''
    outerEllipseSemiX = int(ratio*innerEllipseSemiX)
    outerEllipseSemiY = int(ratio*innerEllipseSemiY)
    rr, cc = ellipse_perimeter(innerEllipseCenterX, innerEllipseCenterY,
                               outerEllipseSemiY, outerEllipseSemiX, orientation=np.pi*1.5)
    outerEllipseVerts = np.dstack([rr, cc])[0]
    # drawPointsOnImg(outerEllipseVerts, imgHR, 'r')

    '''10. head ellipoid (outer ellipse)'''
    '''!!! F I N A L L Y !!!'''
    maxminDict = maxminXYZ(vLinesHR)
    maxZ = maxminDict['maxZCoord'][2]
    minZ = maxminDict['minZCoord'][2]
    ellipsoidHeadVLines, ellipsoidHeadXY, ellipsoidHeadXZ, ellipsoidHeadYZ, ellipsoidHeadXYZ = ellipsoidHead(
        outerEllipseSemiX, outerEllipseSemiY, maxZ - minZ, innerEllipseCenterX, innerEllipseCenterY, minZ)
    # drawPointsOnImg(ellipsoidHeadXY, imgHR, 'b')
    # drawPointsOnImg(ellipsoidHeadXZ, imgHR, 'r')
    # drawPointsOnImg(ellipsoidHeadYZ, imgHR, 'g')

    '''11. hair vLines: z = -1 --> z on ellipsoid'''
    newHairPointsVlines = []
    for hairPointsVline in hairPointsVlines:
        v, x, y, z, r, g, b = hairPointsVline.split()
        maxZ = 0
        for (x0, y0, z0) in ellipsoidHeadXYZ:
            if int(float(x)) == int(float(x0)) and int(float(y)) == int(float(y0)) and float(z0) > 0:
                # print int(float(x0)), int(float(y0)), int(float(z0))
                if int(float(z0)) > int(float(z)) and int(float(z0)) > maxZ:
                    maxZ = int(float(z0))
                    print maxZ
        newHairPointsVline = '{} {} {} {} {} {} {}'.format(
            v, x, y, maxZ, r, g, b)
        newHairPointsVlines.append(newHairPointsVline)
    # print hairPointsVlines
    # print newHairPointsVlines
    assert len(hairPointsVlines) == len(newHairPointsVlines)

    '''12. HR: origin vLines = face landmark vLines + new hair vLines'''
    originVlines = faceLandmarkVlines+newHairPointsVlines

    '''13. HR: turn face and hair'''
    turnAngle = 10
    turnDirection = ['left', 'right']
    turnCenterMode = 'maxY'
    leftTurnVLines = turnHR(originVlines, turnAngle,
                            turnDirection[0], turnCenterMode)
    rightTurnVLines = turnHR(originVlines, turnAngle,
                             turnDirection[1], turnCenterMode)

    assert len(originVlines) == len(leftTurnVLines) == len(rightTurnVLines)

    '''14. HR: turn 3D --> 2D'''
    originPointsHR = []
    leftTurnPointsHR = []
    rightTurnPointsHR = []
    for originVline, leftTurnVLine, rightTurnVLine in zip(originVlines, leftTurnVLines, rightTurnVLines):
        _, x, y, _, _, _, _ = originVline.split()
        originPointsHR.append((float(x), float(y)))
        _, x, y, _, _, _, _ = leftTurnVLine.split()
        leftTurnPointsHR.append((float(x), float(y)))
        _, x, y, _, _, _, _ = rightTurnVLine.split()
        rightTurnPointsHR.append((float(x), float(y)))

    assert len(originPointsHR) == len(
        leftTurnPointsHR) == len(rightTurnPointsHR)

    '''15. edge points on outer ellipse'''
    edgePoints = edgePointsOnOuterEllipse(outerEllipseVerts)

    '''16. final origin and turn points'''
    originPointsHRFinal = originPointsHR+edgePoints
    leftTurnPointsHRFinal = leftTurnPointsHR+edgePoints
    rightTurnPointsHRFinal = rightTurnPointsHR+edgePoints

    '''17. tri.txt'''
    triList = generateTriList(
        originPointsHRFinal, imgHR, triTxtPath='./turnTri.txt')

    return originPointsHRFinal, leftTurnPointsHRFinal, rightTurnPointsHRFinal, triList
Beispiel #4
0
def main2D_3D_2D_HR_NodHair():
    '''1. read origin obj and image'''
    objPath = '../../github/vrn-07231340/obj/trump-12.obj'
    objLines, vLines, fLines = readObj(objPath)
    imgLRPath = '../../github/vrn-07231340/examples/scaled/trump-12.jpg'
    imgLR = cv2.imread(imgLRPath)
    imgHRPath = '../../github/vrn-07231340/examples/trump-12.jpg'
    imgHR = cv2.imread(imgHRPath)

    '''2. origin LR 2D landmark --> origin 3D landmark'''
    '''2.1 origin LR 2D landmark list [x, y]'''
    originLandmark2DLRList = getLandmark2D(imgLR)
    '''2.2 origin 3D landmark list [[[x, y], [(line1, vLine1), (line2, vLine2)]], ... ]'''
    originLandmark3DList = getLandmark3D(originLandmark2DLRList, vLines)
    '''2.3 OPTION 1: 相同(x, y)的情况下,选z最大的3D landmark'''
    originLandmark3DList = optionChooseZMax(originLandmark3DList)

    '''3. 3D model nod'''
    nodAngle = 10
    nodCenterMode = 'maxY'
    nodObjLines = nod(objPath, nodAngle, nodCenterMode)

    '''4. nod 3D landmark list'''
    nodVLines = objLines2vLines(nodObjLines)
    nodLandmark3DList = getNodLandmark3D(nodVLines, originLandmark3DList)

    '''5. nod 3D landmark --> nod LR 2D landmark'''
    nodLandmark2DLR = [i[2] for i in nodLandmark3DList]

    '''6. origin 2D landmark'''
    originLandmark2DLR = [(i[0][0], i[0][1]) for i in nodLandmark3DList]

    assert len(originLandmark2DLR) == len(nodLandmark2DLR)

    '''7. LR --> HR: origin and nod face landmark'''
    originLandmark2DHR = lr2hr(imgLR, imgHR, originLandmark2DLR)
    nodLandmark2DHR = lr2hr(imgLR, imgHR, nodLandmark2DLR)

    '''8. HR: collar detection'''
    _, collarPoint = collarDetection(imgHR, minSize=1200, offset=15)

    '''9. HR: hair detection'''
    originHairPoints = hairDetection(imgHR, minSize=20000)

    '''10. HR: nod hair points'''
    '''??? nod center ???'''
    nodAngleHair = 18
    # drawPointsOnImg(originHairPoints, imgHR, 'r', radius=3)
    # nodHairPoints = nodHairHR(
    # objLines, nodAngleHair, nodCenterMode, originHairPoints, minZ=100.0)
    nodHairPoints = nodHairHR_m(
        nodAngleHair, collarPoint, originHairPoints, minZ=100.0)
    # for (x, y), (i, j) in zip(nodHairPoints, nodHairPoints_m):
    #     if x == i and y == j:
    #         pass
    #     else:
    #         print 'yes'

    '''10. HR: all origin points and nod points'''
    originPoints = originLandmark2DHR+originHairPoints
    nodPoints = nodLandmark2DHR+nodHairPoints
    assert len(originPoints) == len(nodPoints)
    # drawPointsOnImg(originPoints, imgHR, 'g', radius=2)

    '''11. inner ellipse'''
    left = min(originPoints, key=lambda x: x[0])[0]
    right = max(originPoints, key=lambda x: x[0])[0]
    up = min(originPoints, key=lambda x: x[1])[1]
    bottom = max(originPoints, key=lambda x: x[1])[1]
    innerEllipseCenterX = int((left+right)/2.0)
    innerEllipseCenterY = int((up+bottom)/2.0)
    innerEllipseSemiX = int((right-left)/2.0)
    innerEllipseSemiY = int((bottom-up)/2.0)
    rr, cc = ellipse_perimeter(innerEllipseCenterX, innerEllipseCenterY,
                               innerEllipseSemiY, innerEllipseSemiX, orientation=np.pi*1.5)
    innerEllipseVerts = np.dstack([rr, cc])[0]

    '''12. outer ellipse'''
    '''12.1 ratio = outer ellipse / inner ellipse'''
    '''     椭圆心和衣领的线段  和  椭圆的交点'''
    minDistance = np.inf
    for pt in innerEllipseVerts:
        distance = twoPointsDistance(pt, collarPoint)
        if distance < minDistance:
            minDistance = distance
            ratio = twoPointsDistance((innerEllipseCenterX, innerEllipseCenterY), collarPoint) / \
                twoPointsDistance(
                    (innerEllipseCenterX, innerEllipseCenterY), pt)
    '''12.2 outer ellipse'''
    outerEllipseSemiX = int(ratio*innerEllipseSemiX)
    outerEllipseSemiY = int(ratio*innerEllipseSemiY)
    rr, cc = ellipse_perimeter(innerEllipseCenterX, innerEllipseCenterY,
                               outerEllipseSemiY, outerEllipseSemiX, orientation=np.pi*1.5)
    outerEllipseVerts = np.dstack([rr, cc])[0]

    '''13. edge points on outer ellipse'''
    edgePoints = edgePointsOnOuterEllipse(outerEllipseVerts)

    '''14. final origin and nod HR points '''
    originPointsFinal = originPoints+edgePoints
    nodPointsFinal = nodPoints+edgePoints
    assert len(originPointsFinal) == len(nodPointsFinal)
    drawPointsOnImg(originPointsFinal, imgHR, 'b', radius=2)
    drawPointsOnImg(originPoints, imgHR, 'r', radius=2)
    drawPointsOnImg(nodPointsFinal, imgHR, 'g', radius=2)

    '''15. tri.txt'''
    triList = generateTriList(originPointsFinal, imgHR,
                              triTxtPath='./nodTri.txt')

    '''16. warp'''
    imgMorph = morph_modify_for_2D3D2D_low_resolution(
        originPointsFinal, nodPointsFinal, imgHR, triList)
    imshow('imgMorph', imgMorph)
    cv2.imwrite('./imgMorph_{}2.png'.format(nodAngleHair), imgMorph)

    return originPointsFinal, nodPointsFinal, triList