# need to find red zones out of 9 zones in the img from PIL import Image, ImageFont, ImageDraw, features import math import json def getFileJson(fileName): with open(fileName, encoding="utf8") as f: jsonStr = f.read() return json.loads(jsonStr) # expects a dictionary def getRedZones(imgPath, isCmap2=False): img = Image.open(imgPath) pixelValues = list(img.getdata()) colors = img.getcolors() # print("colors: ", colors) # print("totalPixels: ", len(pixelValues)) # print("pixelValues: ", pixelValues[:1000]) # for i in range(len(pixelValues)): # pixelData = pixelValues[i] # if pixelData[3] == 255: # print(i, pixelData) # return # return imgSize = img.size # w-h # print("imgSize: ", imgSize) imgWidth = imgSize[0] imgHeight = imgSize[1] zoneWidth = float(imgWidth) / 3 zoneHeight = float(imgHeight) / 3 redZoneMatrix = {} # red zone area pixels fieldAreaMatrix = {} # total zone area pixels # print("zoneWidth, zoneHeight: ", zoneWidth, zoneHeight) for i in range(9): addZoneToRawMatixIfNone(redZoneMatrix, i + 1) fieldAreaMatrix[i + 1] = 0 for x in range(imgWidth): for y in range(imgHeight): zoneCol = math.ceil((x + 1) / zoneWidth) zoneRow = math.ceil((y + 1) / zoneHeight) # print("col, row: ", x, y, zoneCol, zoneRow, (x + 1), (x + 1) / zoneWidth) zoneNo = (zoneRow - 1) * 3 + zoneCol # assuming it to be tuple of rgba pixelData = pixelValues[y * imgWidth + x] if len(pixelData) > 3: isFieldPixel = pixelData[3] == 255 else: isFieldPixel = True if isFieldPixel: if zoneNo not in fieldAreaMatrix: fieldAreaMatrix[zoneNo] = 0 fieldAreaMatrix[zoneNo] += 1 isRedZonePixel = findIfRedZonePixel(pixelData, isCmap2) if isRedZonePixel: isLeftInZone = getIsLeftZone(zoneNo, x, y, imgWidth, imgHeight) # addZoneToRawMatixIfNone(redZoneRawMatrix, zoneNo) redZoneMatrix[zoneNo]["total"] += 1 redZoneMatrix[zoneNo]["left" if isLeftInZone else "right"] += 1 # print("redZones: ", redZoneMatrix) # print("zoneAreas: ", fieldAreaMatrix) # get redZoneMatrix from raw totalFieldArea = sum(fieldAreaMatrix.values()) # print("zoneAreaSum: ", totalFieldArea) minArea = 0.02 * totalFieldArea for zoneNo, redCount in redZoneMatrix.items(): if zoneNo != 5 and (fieldAreaMatrix[zoneNo] or 0) < minArea: # shift this zone's redCount to adjecent zones leftZoneNo = getAdjecentZoneNo(zoneNo, True, fieldAreaMatrix, minArea) # addZoneToRawMatixIfNone(redZoneRawMatrix, leftZoneNo, fieldAreaMatrix, minArea) redZoneMatrix[leftZoneNo]["total"] += redCount["left"] redZoneMatrix[leftZoneNo]["right"] += redCount["left"] rightZoneNo = getAdjecentZoneNo(zoneNo, False, fieldAreaMatrix, minArea) # addZoneToRawMatixIfNone(redZoneRawMatrix, rightZoneNo, fieldAreaMatrix, minArea) redZoneMatrix[rightZoneNo]["total"] += redCount["right"] redZoneMatrix[rightZoneNo]["right"] += redCount["right"] redZoneMatrix[zoneNo]["total"] = 0 redZoneMatrix[zoneNo]["right"] = 0 redZoneMatrix[zoneNo]["left"] = 0 # print(zoneNo, leftZoneNo, rightZoneNo) # print("totalRedArea: ", sum(map(returnZoneTotal, redZoneMatrix.values()))) redZones = [] # print(redZoneMatrix) for i in range(9): if ( redZoneMatrix[i + 1]["total"] > redZonePercentage / 100 * fieldAreaMatrix[i + 1] ): redZones.append(i + 1) return redZones def getRedZones2(imgPath, isCmap2=False): """It Returns top 3 red zones present. Ignores zone with area less than 7% of total. Red zone is defined as a zone with atleast 15% bad area of the zone area""" img = Image.open(imgPath) pixelValues = list(img.getdata()) colors = img.getcolors() # print("colors: ", colors) # print("totalPixels: ", len(pixelValues)) # print("pixelValues: ", pixelValues[:1000]) # for i in range(len(pixelValues)): # pixelData = pixelValues[i] # if pixelData[3] == 255: # print(i, pixelData) # return # return imgSize = img.size # w-h # print("imgSize: ", imgSize) imgWidth = imgSize[0] imgHeight = imgSize[1] zoneWidth = imgWidth / 3 zoneHeight = imgHeight / 3 redZoneMatrix = {} # red zone area pixels fieldAreaMatrix = {} # total zone area pixels for i in range(9): addZoneToRawMatixIfNone(redZoneMatrix, i + 1) fieldAreaMatrix[i + 1] = 0 for x in range(imgWidth): for y in range(imgHeight): zoneCol = math.ceil((x + 1) / zoneWidth) zoneRow = math.ceil((y + 1) / zoneHeight) zoneNo = (zoneRow - 1) * 3 + zoneCol # assuming it to be tuple of rgba pixelData = pixelValues[y * imgWidth + x] if len(pixelData) > 3: isFieldPixel = pixelData[3] == 255 else: isFieldPixel = True if isFieldPixel: if zoneNo not in fieldAreaMatrix: fieldAreaMatrix[zoneNo] = 0 fieldAreaMatrix[zoneNo] += 1 isRedZonePixel = findIfRedZonePixel(pixelData, isCmap2) if isRedZonePixel: isLeftInZone = getIsLeftZone(zoneNo, x, y, imgWidth, imgHeight) # addZoneToRawMatixIfNone(redZoneRawMatrix, zoneNo) redZoneMatrix[zoneNo]["total"] += 1 redZoneMatrix[zoneNo]["left" if isLeftInZone else "right"] += 1 # print("redZones: ", redZoneMatrix) # print("zoneAreas: ", fieldAreaMatrix) # get redZoneMatrix from raw totalFieldArea = sum(fieldAreaMatrix.values()) # print("zoneAreaSum: ", totalFieldArea) minArea = 0.02 * totalFieldArea for zoneNo, redCount in redZoneMatrix.items(): if zoneNo != 5 and (fieldAreaMatrix[zoneNo] or 0) < minArea: # shift this zone's redCount to adjecent zones leftZoneNo = getAdjecentZoneNo(zoneNo, True, fieldAreaMatrix, minArea) # addZoneToRawMatixIfNone(redZoneRawMatrix, leftZoneNo, fieldAreaMatrix, minArea) redZoneMatrix[leftZoneNo]["total"] += redCount["left"] redZoneMatrix[leftZoneNo]["right"] += redCount["left"] rightZoneNo = getAdjecentZoneNo(zoneNo, False, fieldAreaMatrix, minArea) # addZoneToRawMatixIfNone(redZoneRawMatrix, rightZoneNo, fieldAreaMatrix, minArea) redZoneMatrix[rightZoneNo]["total"] += redCount["right"] redZoneMatrix[rightZoneNo]["right"] += redCount["right"] redZoneMatrix[zoneNo]["total"] = 0 redZoneMatrix[zoneNo]["right"] = 0 redZoneMatrix[zoneNo]["left"] = 0 # print(zoneNo, leftZoneNo, rightZoneNo) # print("totalRedArea: ", sum(map(returnZoneTotal, redZoneMatrix.values()))) redZones = {} # print(redZoneMatrix) for i in range(9): zoneRedArea = redZoneMatrix[i + 1]["total"] zoneTotalArea = fieldAreaMatrix[i + 1] if zoneRedArea > 0.15 * zoneTotalArea and zoneTotalArea > 0.07 * totalFieldArea: redZones[i + 1] = zoneRedArea redZones = dict(sorted(redZones.items(), key=lambda item: item[1], reverse=True)) return list(redZones.keys())[:3] def returnZoneTotal(zoneData): return zoneData["total"] zoneOrder = [1, 2, 3, 6, 9, 8, 7, 4] zones = [1, 2, 3, 4, 5, 6, 7, 8, 9] def getAdjecentZoneNo(zoneNo, isLeft, areaMatrix, minArea): # print(zoneNo, isLeft) zoneIndex = zoneOrder.index(zoneNo) zone = zoneOrder[(zoneIndex + (-1 if isLeft else 1)) % 8] if (areaMatrix[zone] or 0) < minArea: zone = getAdjecentZoneNo(zone, isLeft, areaMatrix, minArea) return zone def getIsLeftZone(zoneNo, x, y, imgWidth, imgHeight): if zoneNo == 2: return x < imgWidth / 2 if zoneNo == 6: return y < imgHeight / 2 if zoneNo == 8: return x > imgWidth / 2 if zoneNo == 4: return y > imgHeight / 2 if zoneNo == 1: return y > x * imgHeight / imgWidth if zoneNo == 3: return y < (imgWidth - x) * imgHeight / imgWidth if zoneNo == 9: return (imgHeight - y) > (imgWidth - x) * imgHeight / imgWidth if zoneNo == 7: return (imgHeight - y) < x * imgHeight / imgWidth def addZoneToRawMatixIfNone(matrix, zoneNo): if zoneNo not in matrix: matrix[zoneNo] = {"total": 0, "left": 0, "right": 0} redZonePercentage = 40 # (255, 240, 179, 255), deepRedPixels = [(234, 77, 57, 255), (173, 5, 53, 255)] redPixels = [ (251, 193, 126, 255), (247, 137, 89, 255), (234, 77, 57, 255), (173, 5, 53, 255), ] redPixels2 = [ (13, 13, 13, 255), (191, 191, 191, 255), (219, 219, 219, 255), (235, 235, 235, 255), (254, 250, 202, 255), (238, 232, 182, 255), (222, 218, 157, 255), (205, 200, 132, 255), (191, 183, 108, 255), (175, 195, 98, 255), (164, 205, 87, 255), ] # elseif ind_i>0.15 && ind_i <= 0.175 # c_map2(i,1) = 164; # c_map2(i,2) = 205; # c_map2(i,3) = 87; # elseif ind_i>0.175 && ind_i <= 0.2 # c_map2(i,1) = 127; # c_map2(i,2) = 179; # c_map2(i,3) = 71; # elseif ind_i>0.2 && ind_i <= 0.25 # c_map2(i,1) = 111; # c_map2(i,2) = 161; # c_map2(i,3) = 64; def findIfRedZonePixel(pixelData, isCmap2): return checkIfColorInList(pixelData, (redPixels if not isCmap2 else redPixels2)) for redPixelData in redPixels if not isCmap2 else redPixels2: if abs(sum(redPixelData) - sum(pixelData)) < 10: return True return False def checkIfColorInList(color, list): for pixelData in list: if abs(sum(pixelData) - sum(color)) < 10: return True return False def getInstructionsByZones(redZones, translations, isIrri, lang): if lang in ["hi", "en"]: irriZones = redZones if isIrri else [] cropZones = [] if isIrri else redZones templateCode = 1 if len(redZones) == 0 else 0 template = "%s%s" % ( templateCode if not isIrri else "_", templateCode if isIrri else "_", ) return getSmsFullInstructionsByZones( template, irriZones, cropZones, translations, lang ) result = "%s- %s" % ( translations["forCropProbInstruc" if not isIrri else "forIrriProbInstruc"], ", ".join(map(zoneToStr, redZones)), ) return result def getFullDirByCode(code): if code == "N": return "north" if code == "W": return "west" if code == "E": return "east" if code == "C": return "ceNter" if code == "S": return "south" rtlLangs = ["ar"] def getLocalDirByZone(zone, translations, langCode, addNewLine=True): newLineTxt = "\n" if addNewLine else " " if zone == 1: if langCode in rtlLangs: return ( translations[getFullDirByCode("W")] + newLineTxt + translations[getFullDirByCode("N")] ) return ( translations[getFullDirByCode("N")] + newLineTxt + translations[getFullDirByCode("W")] ) if zone == 2: return translations[getFullDirByCode("N")] if zone == 3: if langCode in rtlLangs: return ( translations[getFullDirByCode("E")] + newLineTxt + translations[getFullDirByCode("N")] ) return ( translations[getFullDirByCode("N")] + newLineTxt + translations[getFullDirByCode("E")] ) if zone == 4: return translations[getFullDirByCode("W")] if zone == 5: return translations[getFullDirByCode("C")] if zone == 6: return translations[getFullDirByCode("E")] if zone == 7: if langCode in rtlLangs: return ( translations[getFullDirByCode("W")] + newLineTxt + translations[getFullDirByCode("S")] ) return ( translations[getFullDirByCode("S")] + newLineTxt + translations[getFullDirByCode("W")] ) if zone == 8: return translations[getFullDirByCode("S")] if zone == 9: if langCode in rtlLangs: return ( translations[getFullDirByCode("E")] + newLineTxt + translations[getFullDirByCode("S")] ) return ( translations[getFullDirByCode("S")] + newLineTxt + translations[getFullDirByCode("E")] ) def getLocalDirAbrByZone(zone, translations, langCode, addNewLine=False): newLineTxt = "\n" if addNewLine else " " if zone == 1: if langCode in rtlLangs: return "W" + newLineTxt + "N" return "N" + newLineTxt + "W" if zone == 2: return "N" if zone == 3: if langCode in rtlLangs: return "E" + newLineTxt + "N" return "N" + newLineTxt + "E" if zone == 4: return "W" if zone == 5: return "C" if zone == 6: return "E" if zone == 7: if langCode in rtlLangs: return "W" + newLineTxt + "S" return "S" + newLineTxt + "W" if zone == 8: return "S" if zone == 9: if langCode in rtlLangs: return "E" + newLineTxt + "S" return "S" + newLineTxt + "E" def getSmsInstructionsByZones(redZones, translations, langCode): def getLocalDir(zone): return getLocalDirByZone(zone, translations, langCode, False) zoneList = list(map(getLocalDir, redZones)) # print(zoneList) result = ", ".join(zoneList) return result smsTrans = { "hi": { "sms00": "सिचाई जांच की आवश्यकता {1} और फसल जांच की आवश्यकता {2} है|", "sms10": "फसल जांच की आवश्यकता {2} है और सिचाई अच्छी स्तिथि में है|", "sms01": "सिचाई जांच की आवश्यकता {1} है और फसल अच्छी स्तिथि में है|", "sms11": "सिचाई और फसल दोनों अच्छी स्तिथि में है।", "sms_1": "सिचाई अच्छी स्तिथि में है।", "sms1_": "फसल अच्छी स्तिथि में है।", "sms_0": "सिचाई जांच की आवश्यकता {1} है।", "sms0_": "फसल जांच की आवश्यकता {2} है।", "smsMain": "{1}{2}", "smsOther": "{1} के अलावा{2}", "smsNum2": " दिशाओं में", "smsMulti": "", "smsNumMax": 2, "smsAll": "पुरे खेत में", }, "en": { "sms00": "irrigation inspection is required in {1} and crop inspection is required in {2} of your field.", "sms01": "irrigation inspection is required in {1} of your field and crop is in good condition.", "sms10": "crop inspection is required in {2} of your field and irrigation is in good condition.", "sms11": "both irrigation and crop are in good condition.", "sms_1": "Irrigation are in good condition.", "sms1_": "Crop are in good condition.", "sms_0": "Irrigation inspection is required in {1} of your field.", "sms0_": "Crop inspection is required in {2} of your field.", "smsMain": "{1} direction{2}", "smsOther": "directions other than {1}", "smsNum2": "", "smsNum2_5": "s", "smsMulti": "2", "smsNumMax": 2, "smsAll": "all directions", }, } def saveTxtToFile(txt, outFile="tmpTxtFile.txt"): with open(outFile, "w", encoding="utf8") as f: f.write(txt) def replaceDirsIn(zones, translations, langCode, isMain=True): langTrans = translations # smsTrans[langCode] resultStr = langTrans[ "sms%s" % ("All" if len(zones) == 9 else "Main" if isMain else "Other") ] # print(resultStr) isRtlLang = langCode in rtlLangs firstBrac = "{" if isRtlLang else "{" secBrac = "}" if isRtlLang else "}" resultStr = resultStr.replace( "%s1%s" % (firstBrac, secBrac), getSmsInstructionsByZones(zones, translations, langCode), ) # print(resultStr) multiNums = langTrans["smsMulti"].split(",") numMax = int(langTrans["smsNumMax"]) # print(numMax, multiNums) index = 2 while index <= numMax: indexKey = "smsNum%s" % (index) # print(index, indexKey) if str(index) in multiNums: if len(zones) == 1: resultStr = resultStr.replace( "%s%s%s" % (firstBrac, index, secBrac), langTrans.get(indexKey + "_3", langTrans.get(indexKey)), ) else: resultStr = resultStr.replace( "%s%s%s" % (firstBrac, index, secBrac), langTrans[indexKey + "_5"] ) else: resultStr = resultStr.replace( "%s%s%s" % (firstBrac, index, secBrac), langTrans[indexKey] ) index += 1 # print(resultStr) return resultStr def getSmsFullInstructionsByZones( templateType, irriZones, cropZones, translations, langCode ): if irriZones == None or cropZones == None: return translations.get("NoData") # expects only for hi; expects zones to be non-None irri2Zones = [x for x in zones if x not in irriZones] crop2Zones = [x for x in zones if x not in cropZones] if True: irriDirsStr = replaceDirsIn(irriZones, translations, langCode) irri2DirsStr = replaceDirsIn(irri2Zones, translations, langCode, False) cropDirsStr = replaceDirsIn(cropZones, translations, langCode) crop2DirsStr = replaceDirsIn(crop2Zones, translations, langCode, False) else: irri2DirsStr = "" irriDirsStr = "" crop2DirsStr = "" cropDirsStr = "" irriType = 1 if len(irriDirsStr) < len(irri2DirsStr) else 2 cropType = 1 if len(cropDirsStr) < len(crop2DirsStr) else 2 templates = translations # smsTrans[langCode] result = templates["sms%s" % (templateType)] result = result.replace("{1}", irriDirsStr if irriType == 1 else irri2DirsStr) result = result.replace("{2}", cropDirsStr if cropType == 1 else crop2DirsStr) # return [templateType, irriType, cropType, result] return result def getFullInstructions(templateType, mZones, translations, langCode, replaceNo=0): # expects only single type template; expects zones to be non-None zones2 = [x for x in zones if x not in mZones] if True: # if langCode in ["hi", "en", "pa"]: dirsStr = replaceDirsIn(mZones, translations, langCode) dirs2Str = replaceDirsIn(zones2, translations, langCode, False) else: irri2DirsStr = "" irriDirsStr = "" dirs2Str = "" dirsStr = "" cropType = 1 if len(dirsStr) < len(dirs2Str) else 2 result = translations[templateType] isRtlLang = langCode in rtlLangs firstBrac = "{" if isRtlLang else "{" secBrac = "}" if isRtlLang else "}" replaceNoStr = "%s%s%s" % (firstBrac, replaceNo, secBrac) # print(replaceNoStr) result = result.replace(replaceNoStr, dirsStr if cropType == 1 else dirs2Str) # return [templateType, irriType, cropType, result] return result def zoneToStr(zoneNo): if zoneNo == 1: return "NW" if zoneNo == 2: return "N" if zoneNo == 3: return "NE" if zoneNo == 4: return "W" if zoneNo == 5: return "C" if zoneNo == 6: return "E" if zoneNo == 7: return "SW" if zoneNo == 8: return "S" if zoneNo == 9: return "SE" imgPath = "report_images/demoPics/1726236049316_20241014_rvi.png" # "sampleField.png" # redZones = getRedZones(imgPath, False) # redZones = 1/float(5) # print(redZones) # 299-E61919, 60-3D1362, 17-11A75E, 247-F78959, 145-93102D # 186, 227, 131-B9E382,12182402,12247939; # create field dirc img def createFieldDirImg( imgPath, savePath="report_images/demoPics/dirImg.png", translations=None, langCode=None, ): img = Image.open(imgPath) imgWidth = img.size[0] imgHeight = img.size[1] # make single color img pixelMap = img.load() for x in range(imgWidth): for y in range(imgHeight): if 0 == pixelMap[x, y][3]: pixelMap[x, y] = (255, 255, 255, 0) else: pixelMap[x, y] = (255, 240, 179, 255) # resize if needed smallerLen = min(imgWidth, imgHeight) factor = 1 if smallerLen < 300: factor = round(300 / smallerLen, 1) if factor % 0.2 == 0.1: factor += 0.1 if factor != 1: img = img.resize((round(imgWidth * factor), round(imgHeight * factor))) imgHeight = img.size[1] imgWidth = img.size[0] # add zone lines editableImg = ImageDraw.Draw(img) width1 = round(imgWidth / 3) width2 = round(imgWidth * 2 / 3) height1 = round(imgHeight / 3) height2 = round(imgHeight * 2 / 3) editableImg.line([(width1, 0), (width1, imgHeight)], (0, 0, 0), 2) editableImg.line([(width2, 0), (width2, imgHeight)], (0, 0, 0), 2) editableImg.line([(0, height1), (imgWidth, height1)], (0, 0, 0), 2) editableImg.line([(0, height2), (imgWidth, height2)], (0, 0, 0), 2) # add direction text def getLocalName(zone): # langCode is only expected as hi return getLocalDirByZone(zone, translations, langCode) if langCode == "bn": fontPath = "report_fonts/Hind_Siliguri/HindSiliguri-Bold.ttf" fontSize = 26 fontDir = "ltr" elif langCode == "te": fontPath = "report_fonts/Noto_Sans_Telugu/static/NotoSansTelugu/NotoSansTelugu-Bold.ttf" fontSize = 24 fontDir = "ltr" elif langCode == "ta": fontPath = ( "report_fonts/Noto_Sans_Tamil/static/NotoSansTamil/NotoSansTamil-Bold.ttf" ) fontSize = 20 fontDir = "ltr" elif langCode == "kn": fontPath = "report_fonts/Noto_Sans_Kannada/static/NotoSansKannada/NotoSansKannada-Bold.ttf" fontSize = 23 fontDir = "ltr" elif langCode == "ml": fontPath = "report_fonts/Noto_Sans_Malayalam/static/NotoSansMalayalam_ExtraCondensed-SemiBold.ttf" fontSize = 20 fontDir = "ltr" # savePath="report_images/demoPics/dirImgml-ec-sb.png" elif langCode == "gu": fontPath = "report_fonts/Hind_Vadodara/HindVadodara-Bold.ttf" fontSize = 23 fontDir = "ltr" elif langCode == "or": fontPath = "report_fonts/Noto_Sans_Oriya/static/NotoSansOriya-Bold.ttf" fontSize = 26 fontDir = "ltr" elif langCode == "pa": fontPath = "report_fonts/Mukta_Mahee/MuktaMahee-Bold.ttf" fontSize = 28 fontDir = "ltr" elif langCode == "ar": fontPath = "report_fonts/Tajawal/Tajawal-Bold.ttf" fontSize = 26 fontDir = "rtl" elif langCode == "uz": fontPath = "report_fonts/Mukta_Mahee/MuktaMahee-Bold.ttf" fontSize = 22 fontDir = "ltr" else: fontPath = "report_fonts/Noto_Sans/NotoSans-Bold.ttf" fontSize = 26 fontDir = "ltr" if translations != None: zoneNames = list(map(getLocalName, zones)) else: zoneNames = list(map(zoneToStr, zones)) fontSize = 50 fontDir = "ltr" font = ImageFont.truetype(fontPath, fontSize) widthF = round(max(0, (width1 - 80) / 2)) heightF = round(max(0, (height1 - 100) / 2)) # print(zoneNames) for zone in zones: dirOffset = getDirOffsetByZone( zone, width1, width2, widthF, height1, height2, heightF ) index = zone - 1 zoneName = zoneNames[index] editableImg.text( dirOffset, zoneName, (255, 50, 36), font, layout_engine=ImageFont.LAYOUT_RAQM, direction=fontDir, ) # editableImg.text((widthF, heightF), "NW", (255, 50, 36), font) # editableImg.text((width1+widthF, heightF), "N", (255, 50, 36), font) # editableImg.text((width2+widthF, heightF), "NE", (255, 50, 36), font) # editableImg.text((widthF, height1+heightF), "W", (255, 50, 36), font) # editableImg.text((width1+widthF, height1+heightF), # "C", (255, 50, 36), font) # editableImg.text((width2+widthF, height1+heightF), # "E", (255, 50, 36), font) # editableImg.text((widthF, height2+heightF), "SW", (255, 50, 36), font) # editableImg.text((width1+widthF, height2+heightF), # "S", (255, 50, 36), font) # editableImg.text((width2+widthF, height2+heightF), # "SE", (255, 50, 36), font) # save the result img.save(savePath) def getDirOffsetByZone(zone, width1, width2, widthF, height1, height2, heightF): if zone == 1: return (widthF, heightF) if zone == 2: return (width1 + widthF, heightF) if zone == 3: return (width2 + widthF, heightF) if zone == 4: return (widthF, height1 + heightF) if zone == 5: return (width1 + widthF, height1 + heightF) if zone == 6: return (width2 + widthF, height1 + heightF) if zone == 7: return (widthF, height2 + heightF) if zone == 8: return (width1 + widthF, height2 + heightF) if zone == 9: return (width2 + widthF, height2 + heightF) # lang = "ar" # # template2 = "dem0" # template = "00" #irri, crop; (in single) crop, irri; 0 means need attention # irriRedZones = [1, 2, 3, 4, 5, 6, 7, 8] # cropRedZones = [1, 2, 3] # # # template = "%s%s" % ( # # # 0 if len(irriRedZones) != 0 else 1, 0 if len(cropRedZones) != 0 else 1) # translations = getFileJson("jsons/app_{langCode}.json".format(langCode=lang)) # smsTxt = replaceDirsIn(cropRedZones, translations, lang) # smsTxt = getSmsFullInstructionsByZones( # template, irriRedZones, cropRedZones, translations, lang) # # smsTxt2 = getFullInstructions( # # template2, cropRedZones, translations, lang, 0) # print(smsTxt) # saveTxtToFile(smsTxt) # print(len(smsTxt)) # "bn", "mr", "te", "ta", "kn", "ar", "en", "hi", "uz", "pa" # langs = ["kn"] # for lang in langs: # translations = getFileJson("jsons/app_{langCode}.json".format(langCode=lang)) # imgToMask = "report_images/demoPics/field_img12_rvi_20221215.png" # # createFieldDirImg(imgToMask, "report_images/demoPics/dirImg12_rvi_20221215.png") # createFieldDirImg(imgToMask, "report_images/demoPics/dirImg%s.png"%(lang), translations, lang) # print("done", lang) def checkAllTranslations(): langs = ["ar"] for lang in langs: result = "" result2 = "" translations = getFileJson("jsons/app_{langCode}.json".format(langCode=lang)) # dem template2 = "dem1" cropRedZones = [1, 2] smsTxt2 = getFullInstructions(template2, cropRedZones, translations, lang, 0) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "dem0" cropRedZones = [1, 2] smsTxt2 = getFullInstructions(template2, cropRedZones, translations, lang, 0) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "dem0" cropRedZones = [1, 2, 3, 4, 5, 6, 7] smsTxt2 = getFullInstructions(template2, cropRedZones, translations, lang, 0) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "dem0" cropRedZones = [1, 2, 3, 4, 5, 6, 7, 8, 9] smsTxt2 = getFullInstructions(template2, cropRedZones, translations, lang, 0) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) # soil template2 = "soil1" cropRedZones = [1, 2] smsTxt2 = getFullInstructions(template2, cropRedZones, translations, lang, 0) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "soil0" cropRedZones = [1, 2] smsTxt2 = getFullInstructions(template2, cropRedZones, translations, lang, 0) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "soil0" cropRedZones = [1, 2, 3, 4, 5, 6, 7] smsTxt2 = getFullInstructions(template2, cropRedZones, translations, lang, 0) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "soil0" cropRedZones = [1, 2, 3, 4, 5, 6, 7, 8, 9] smsTxt2 = getFullInstructions(template2, cropRedZones, translations, lang, 0) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) # irri template2 = "_1" cropRedZones = [1, 2] smsTxt2 = getSmsFullInstructionsByZones( template2, cropRedZones, [], translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "_0" cropRedZones = [1, 2] smsTxt2 = getSmsFullInstructionsByZones( template2, cropRedZones, [], translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "_0" cropRedZones = [1, 2, 3, 4, 5, 6, 7] smsTxt2 = getSmsFullInstructionsByZones( template2, cropRedZones, [], translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "_0" cropRedZones = [1, 2, 3, 4, 5, 6, 7, 8, 9] smsTxt2 = getSmsFullInstructionsByZones( template2, cropRedZones, [], translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) # crop template2 = "1_" cropRedZones = [1, 2] smsTxt2 = getSmsFullInstructionsByZones( template2, [], cropRedZones, translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "0_" cropRedZones = [1, 2] smsTxt2 = getSmsFullInstructionsByZones( template2, [], cropRedZones, translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) # crop-irri template2 = "11" irriRedZones = [1, 2] cropRedZones = [1, 2] smsTxt2 = getSmsFullInstructionsByZones( template2, irriRedZones, cropRedZones, translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "01" smsTxt2 = getSmsFullInstructionsByZones( template2, irriRedZones, cropRedZones, translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "10" smsTxt2 = getSmsFullInstructionsByZones( template2, irriRedZones, cropRedZones, translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) template2 = "00" irriRedZones = [1, 4] smsTxt2 = getSmsFullInstructionsByZones( template2, irriRedZones, cropRedZones, translations, lang ) result += "%s\n%s\n\n" % (template2, smsTxt2) result2 += "%s\n" % (smsTxt2) result += "\n\n%s" % (result2) saveTxtToFile(result, outFile="txts/trans_%s.txt" % (lang)) print("done", lang) # checkAllTranslations() # cloudyPixels = [(255, 255, 0, 255), (0, 0, 0, 255), (255, 255, 255, 255)] def isCloudyImg(tciPath, ndviPath): img = Image.open(tciPath) pixelValues = list(img.getdata()) img2 = Image.open(ndviPath) pixelValues2 = list(img2.getdata()) # colors = img2.getcolors() # print("colors: ", colors) # return # print("totalPixels: ", len(pixelValues)) # print("pixels", pixelValues) if len(pixelValues) > 0: if type(pixelValues[0]) == int: return True print("pixelElementsSize: ", len(pixelValues[0]), len(pixelValues2[0])) # return 0 imgSize = img.size # w-h print("imgSize: ", imgSize) imgWidth = imgSize[0] imgHeight = imgSize[1] fieldPixels = 0 cloudyPixelsNo = 0 ndviReds = 0 # tciChecked = 0 for x in range(imgWidth): for y in range(imgHeight): index = y * imgWidth + x rgbaN = pixelValues2[index] if rgbaN[3] == 255: # have some color on field pixel fieldPixels += 1 isNRed = checkIfColorInList(rgbaN, deepRedPixels) # print("ndvi", isNRed, rgbaN) if isNRed: # ndvi is red ndviReds += 1 rgba = pixelValues[index] # isYellow = rgba[0] >= 240 and rgba[1] >= 230 # isBlack = rgba[2] == 0 and rgba[0] + \ # rgba[1] < 100 and abs(rgba[0]-rgba[1]) < 50 isWhite = rgba[0] > 120 and rgba[1] > 130 and rgba[2] > 130 if isWhite: # tci is black or yellow cloudyPixelsNo += 1 # else: # if tciChecked < 100: # print("tci", rgba, isWhite) # tciChecked += 1 # print("ndviReds", ndviReds) print("cloudyPixels", cloudyPixelsNo) print("fieldPixels", fieldPixels) return cloudyPixelsNo > fieldPixels * 0.3 def analyseColors(etciPath, ndviPath): # analysing for cloudy imgETCI = Image.open(etciPath) imgNDVI = Image.open(ndviPath) pixelValues = list(imgETCI.getdata()) pixelValuesN = list(imgNDVI.getdata()) colorsETCI = imgETCI.getcolors() # colorsNDVI = imgNDVI.getcolors() c_255_255 = 0 c_245_245 = 0 c_240_240 = 0 whites = 0 blacks = 0 fieldPixels = 0 totalPixels = 0 fieldList = [] for color in colorsETCI: count = color[0] rgba = color[1] totalPixels += count if rgba[3] != 0: fieldList.append(color) fieldPixels += count if rgba[0] == 255 and rgba[1] == 255: c_255_255 += count if rgba[2] == 255: whites += count elif rgba[0] >= 245 and rgba[1] >= 245: c_245_245 += count elif rgba[0] >= 240 and rgba[1] >= 240: c_240_240 += count elif rgba[0] == 0 and rgba[1] == 0 and rgba[2] == 0: blacks += count def cloudySort(color): rgba = color[1] return rgba[0] * 4 + rgba[1] * 2 + rgba[2] def countSort(color): return color[0] fieldList.sort(key=cloudySort) fieldList2 = fieldList.copy() fieldList2.sort(key=countSort, reverse=True) imgSize = imgETCI.size # w-h print("imgSize: ", imgSize) imgWidth = imgSize[0] imgHeight = imgSize[1] cloudies = 0 for x in range(imgWidth): for y in range(imgHeight): index = y * imgWidth + x rgba = pixelValues[index] if rgba[3] == 255: rgbaN = pixelValuesN[index] isNRed = checkIfColorInList(rgbaN, redPixels) if isNRed: isYellow = rgba[0] >= 240 and rgba[1] >= 230 isBlack = ( rgba[2] == 0 and rgba[0] + rgba[1] < 100 and abs(rgba[0] - rgba[1]) < 50 ) if isYellow or isBlack: cloudies += 1 # , fieldList, fieldList2[:min(20, len(fieldList2))]) return ( totalPixels, fieldPixels, whites, blacks, c_255_255, c_245_245, c_240_240, cloudies, ) ndviPath = "report_images/demoPics/1723452248313_20240902_ndvi.png" etciPath = "report_images/demoPics/1723452248313_20240902_etci.png" tciPath = "report_images/demoPics/1723452248313_20240902_tci.png" ndwiPath = "report_images/demoPics/field_img14_20220825_etci.png" # print(isCloudyImg(tciPath, ndviPath)) # print(analyseColors(etciPath, ndviPath)) def createDirOnMapImg(dirImgPath, mapImgPath, mapDimens, outPath, addLogo=True): dirImg = Image.open(dirImgPath, "r") mapImg = Image.open(mapImgPath) logoImg = Image.open("report_images/farmonaut_logo_white.png", "r") # 390x113 horiPadPer = mapDimens.get("horiPadPer") verPadPer = mapDimens.get("verPadPer") horiPad = (mapDimens.get("width") * horiPadPer) / (1 + 2 * horiPadPer) # in pixels verPad = (mapDimens.get("height") * verPadPer) / (1 + 2 * verPadPer) # in pixels width = mapDimens.get("width") / (1 + 2 * horiPadPer) # height = mapDimens[1]/(1+2*verPadPer) magnifyRatio = dirImg.size[0] / width finalVerPad = magnifyRatio * verPad logoHeight = finalVerPad * 0.7 print(magnifyRatio, logoHeight, horiPad, verPad) resizedLogoImg = logoImg.resize( (round(logoHeight * 390 / 113), round(logoHeight)), Image.LANCZOS ) # resizedDirImg.save("report_images/demoPics/resizeDirImg.png") # , round(horiPad+width), round(verPad+height) resizedMapImg = mapImg.resize( (round(magnifyRatio * mapImg.size[0]), round(magnifyRatio * mapImg.size[1])), Image.LANCZOS, ) resizedMapImg.paste( dirImg, (round(magnifyRatio * horiPad), round(finalVerPad)), mask=dirImg ) if addLogo: resizedMapImg.paste(resizedLogoImg, mask=resizedLogoImg) resizedMapImg.save(outPath) # dirImgPath="report_images/demoPics/dirImghi.png" # mapImgPath="report_images/demoPics/fieldMap.jpg" # dimens=(167.91809200993967, 335.83618401987934, # 0.5328091778105274, 0.09999999999999996) # 44.64947605769587 153.71462885606567 # aspect: 0.2904699207224087 # new w-h: 76.85731442803284 153.71462885606567 # len 184.4575546272788 # 167.91809200993967 335.83618401987934 18 0.5492486021588433 0.1 0.1 # 92.2287758, 184.46091 (37.845, 15.373)/ # (167.91809200993967, 335.83618401987934, 0.5328091778105274, 0.09999999999999996) # outPath="report_images/demoPics/dirMapImg.png" # createDirOnMapImg(dirImgPath, mapImgPath, dimens, outPath) # def getAvgIndexValue(path): # img = Image.open(path) # pixelValues = list(img.getdata()) # imgSize = img.size # w-h # print("imgSize: ", imgSize) # imgWidth = imgSize[0] # imgHeight = imgSize[1] # for x in range(imgWidth): # for y in range(imgHeight): # index = y * imgWidth + x # rgbaN = pixelValues2[index]